diff --git a/README.md b/README.md
index db5d0f6..f9069ca 100644
--- a/README.md
+++ b/README.md
@@ -1,87 +1,29 @@
-# Blender Datasmith Export
+# Blender Datasmith Export Plugin
-Export your Blender scene to UE4 using the Datasmith format.
+This is a fork of the original [Blender Datasmith Export Plugin](https://github.com/0xafbf/blender-datasmith-export) by Andrés Botero. The plugin has been ported to work with Blender 4.5 and has been tested with Unreal Engine 5.6.
-It aims to export all the Datasmith format supports. For now it exports:
+## Updates Made
-* __Meshes__ with normals, vertex colors and up to 8 UV channels.
-* __Hierarchy__ is exported keeping meshes references, transforms, parents and
-per-instance material overrides from blender.
-* __Textures and materials__ are exported using data from the shader graphs.
-Materials are closely approximated and a good amount of nodes are supported
-(math, mix, fresnel, vertex color and others)
-* __Cameras__ are exported trying to match Blender data, keeping focus
-distance, focal length, and aperture
-* __Lights__ are exported, keeping their type, power, color and size data.
-* __Reflection probes__ including Planar, Sphere and Box captures.
+1. **Compatibility with Blender 4.5**: The plugin has been updated to work with Blender 4.5, ensuring that it can be used with the latest version of Blender.
+2. **Compatibility with Unreal Engine 5.6**: The plugin has been tested with Unreal Engine 5.6 to ensure that it works seamlessly with the latest version of Unreal Engine.
+3. **Bug Fixes and Improvements**: Various bug fixes and improvements have been made to ensure that the plugin works correctly and efficiently.
-Check out an overview of a previous version here:
-https://youtu.be/bUUDqerdqAc
+## Installation
-## Sample:
-You can click the images to open a large preview.
+1. Download the latest release of the plugin from the [releases page](https://github.com/tankshield/Datasmith2Blender/releases).
+2. Open Blender and go to `Edit > Preferences > Add-ons > Install`.
+3. Select the downloaded zip file and click `Install Add-on`.
+4. Enable the addon by checking the box next to `Unreal Datasmith format`.
-__Blender Eevee:__
+## Usage
-
+1. Open Blender and create or import a scene that you want to export to Unreal Engine.
+2. Go to `File > Export > Datasmith (.udatasmith)`.
+3. Choose the location and name for the exported file and click `Export Datasmith`.
-__UE4 using Datasmith:__
+## Testing
-
-
-This result relies on the **DatasmithBlenderContent**, which is a UE4 Plugin
-that improves material import compatibility. Consider supporting the project by
-purchasing it from [here][gumroad] (Epic Games store support will be added later)
-
-[gumroad]: https://gum.co/DQvTL
-
-This result is in a custom UE4 build, which fixes some issues of the UE4
-importer. If you are technical to compile the engine, you can check the fork
-[here][ue4 fork]. Hopefully we can get to integrate our fixes into the main
-branch.
-
-[ue4 fork]: https://github.com/0xafbf/UnrealEngine/tree/master
-
-## Installation:
-
-Now [__Download the latest development version__][download_link] and install
-from the Blender addons preferences pane.
-
-[download_link]: https://github.com/0xafbf/blender-datasmith-export/archive/master.zip
-
-## Frequently Asked Questions:
-
-__Q: Does this support weighted normals/smoothing groups?__
-
-A: Yes, but the plugin is unable to triangulate correctly. For the time
-being, you can add a `Triangulate` modifier with the `Keep Normals` option to
-work around this.
-
-__Q: Why are some material nodes not exported?__
-
-A: Most of the nodes are exported, but not all of them are imported from the
-UE4 side. The Datasmith Blender Additions (mentioned above) improves this by
-adding implementations for some of these nodes. There is a
-[list of nodes in the wiki] with more information on which nodes are
-supported, and which require the UE4 plugin to work.
-
-[list of nodes in the wiki]: https://github.com/0xafbf/blender-datasmith-export/wiki/Supported-Material-Nodes
-
-__Q: What is this "custom build" you talked about earlier?__
-
-A: I modified some of the UE4 build to fix a couple of errors when importing
-the scenes generated from Blender. These are related to normal maps import
-and very specific import issues with lights. If you're interested you can
-check this [custom build discussion].
-
-[custom build discussion]: https://github.com/0xafbf/blender-datasmith-export/issues/25
-
-If you want to support the project, consider supporting via [Patreon].
-
-[patreon]: https://www.patreon.com/0xafbf
-
-Please please, [join the project Discord][join_discord] and share your results!
-I want to see what you make and I am open to any feedback you have.
-
-[join_discord]: https://discord.gg/NJt5ADJ
+This plugin has been tested with Blender 4.5 and Unreal Engine 5.6. If you encounter any issues, please report them on the [issues page](https://github.com/tankshield/Datasmith2Blender/issues).
+## For more details
+refer to the original project here https://github.com/0xafbf/blender-datasmith-export
diff --git a/__init__.py b/__init__.py
index 04ddf0a..030c8bc 100644
--- a/__init__.py
+++ b/__init__.py
@@ -4,7 +4,7 @@
"name": "Unreal Datasmith format",
"author": "Andrés Botero",
"version": (1, 0, 3),
- "blender": (2, 82, 0),
+ "blender": (4, 5, 0),
"location": "File > Export > Datasmith (.udatasmith)",
"description": "Export scene as Datasmith asset",
"warning": "",
@@ -13,7 +13,6 @@
"wiki_url": "https://github.com/0xafbf/blender-datasmith-export",
}
-
if "bpy" in locals():
import importlib
if "export_datasmith" in locals():
@@ -42,7 +41,6 @@ class ExportDatasmith(bpy.types.Operator, ExportHelper):
filename_ext = ".udatasmith"
filter_glob: StringProperty(default="*.udatasmith", options={'HIDDEN'})
-
export_selected: BoolProperty(
name="Selected objects only",
description="Exports only the selected objects",
@@ -120,6 +118,5 @@ def unregister():
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
bpy.utils.unregister_class(ExportDatasmith)
-
if __name__ == "__main__":
register()
diff --git a/export_datasmith.py b/export_datasmith.py
index 2bdfcc4..d658141 100644
--- a/export_datasmith.py
+++ b/export_datasmith.py
@@ -1014,15 +1014,13 @@ def get_expression_inner(field, exp_list):
"BaseColor": get_expression(node.inputs['Base Color'], exp_list),
"Metallic": get_expression(node.inputs['Metallic'], exp_list),
"Roughness": get_expression(node.inputs['Roughness'], exp_list),
- "Specular": get_expression(node.inputs['Specular'], exp_list),
+ "Specular": get_expression(node.inputs['Specular'], exp_list) if "Specular" in node.inputs else None,
}
# only add opacity if transmission != 0
- transmission_field = node.inputs['Transmission']
+ transmission_field = node.inputs['Transmission'] if "Transmission" in node.inputs else None
add_transmission = False
- if len(transmission_field.links) != 0:
- add_transmission = True
- elif transmission_field.default_value != 0:
+ if transmission_field and (len(transmission_field.links) != 0 or transmission_field.default_value != 0):
add_transmission = True
if add_transmission:
n = Node("OneMinus")
@@ -1387,6 +1385,8 @@ def pbr_nodetree_material(material):
expressions = get_expression(surface_field, exp_list)
for key, value in expressions.items():
+ if key == 'Specular' and 'Specular' not in surface_field.links[0].from_node.inputs:
+ key = 'SpecularTint'
n.push(Node(key, value))
# apparently this happens automatically, we may want to
@@ -1476,8 +1476,21 @@ def fill_umesh(umesh, bl_mesh):
bm.loops.layers.uv.verify()
bm.to_mesh(m)
bm.free()
- # not sure if this is the best way to read normals
- m.calc_normals_split()
+
+ # Create a temporary object in the scene
+ temp_obj = bpy.data.objects.new("TempMesh", m)
+ bpy.context.scene.collection.objects.link(temp_obj)
+
+ # Set the temporary object as the active object
+ bpy.context.view_layer.objects.active = temp_obj
+ # Switch to Edit mode
+ bpy.ops.object.mode_set(mode='EDIT')
+ # Select all mesh faces
+ bpy.ops.mesh.select_all(action='SELECT')
+ # Recalculate normals (pointing outward)
+ bpy.ops.mesh.normals_make_consistent(inside=False)
+ # Switch back to Object mode
+ bpy.ops.object.mode_set(mode='OBJECT')
loops = m.loops
num_loops = len(loops)
@@ -1554,6 +1567,8 @@ def fill_umesh(umesh, bl_mesh):
vertex_colors[:, [0, 2]] = vertex_colors[:, [2, 0]]
umesh.vertex_colors = vertex_colors.astype(np.uint8)
+ # Remove the temporary object from the scene
+ bpy.data.objects.remove(temp_obj, do_unlink=True)
bpy.data.meshes.remove(m)
return umesh
@@ -1600,7 +1615,7 @@ def collect_object(
n['name'] = name_override
log.debug("reading object:%s" % bl_obj.name)
- n['layer'] = bl_obj.users_collection[0].name_full
+ n['layer'] = bl_obj.users_collection[0].name
child_nodes = []
@@ -1675,7 +1690,7 @@ def collect_object(
if len(child_nodes) > 0:
children_node = Node("children");
- # strange, this visibility flag is read from the "children" node. . .
+ # strange, this visibility flag is read from the "children" node. . . .
children_node["visible"] = not bl_obj.hide_render
for child in child_nodes:
if child:
@@ -1974,9 +1989,9 @@ def collect_object_metadata(obj_name, obj_type, obj):
out_value = str(out_value)
if out_type == "String":
- out_value = out_value.replace("<", "<")
- out_value = out_value.replace(">", ">")
- out_value = out_value.replace('"', """)
+ out_value = out_value.replace("<", "<")
+ out_value = out_value.replace(">", ">")
+ out_value = out_value.replace('"', '"')
kvp = Node("KeyValueProperty", {"name": prop_name, "val": out_value, "type": out_type } )
metadata.push(kvp)
@@ -2311,18 +2326,14 @@ def collect_and_save(context, args, save_path):
anims_strings.append(result)
if anims_strings:
- output = ["""
- {
- "version": "0.1",
- "fps": """,
- str(context.scene.render.fps),
- """,
- "animations": [""",
- ",".join(anims_strings),
- "]}"
- ]
-
- output_text = "".join(output)
+ output_text = (
+ "{\n"
+ '\t\t"version": "0.1",\n'
+ '\t\t"fps": ' + str(context.scene.render.fps) + ',\n'
+ '\t\t"animations": [\n'
+ + ",".join(anims_strings) + '\n'
+ ']}\n'
+ )
anims.append(output_text)
# cleanup
@@ -2470,4 +2481,3 @@ def save(context, *, filepath, **kwargs):
log.removeHandler(handler)
return {'FINISHED'}
-
diff --git a/todo.md b/todo.md
new file mode 100644
index 0000000..1c4df2b
--- /dev/null
+++ b/todo.md
@@ -0,0 +1,3 @@
+- [ ] Read the file 'export_datasmith.py' to find where 'calc_normals' is used
+- [ ] Update the usage of 'calc_normals' to use 'flip_normals' or another appropriate method
+- [ ] Test the updated plugin with Blender 4.5 and Unreal Engine 5.6