Skip to content

Commit be7f821

Browse files
committed
0_6_0
1 parent 5edbe41 commit be7f821

4 files changed

Lines changed: 239 additions & 59 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,5 @@ Installing an Addon in Blender
9292
![alt](/screenshots/ue_material_setup.png)
9393
## Preferences
9494
![alt](/screenshots/ue_prefs.png)
95+
## Preferences (UE)
96+
![alt](/screenshots/ue_prefs_ue.png)

__init__.py

Lines changed: 141 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"name": "DKS UE",
2121
"description": "Export to UE",
2222
"author": "DigiKrafting.Studio",
23-
"version": (0, 5, 0),
23+
"version": (0, 6, 0),
2424
"blender": (2, 80, 0),
2525
"location": "Info Toolbar, File -> Export",
2626
"wiki_url": "https://github.com/DigiKrafting/blender_addon_ue/wiki",
@@ -88,7 +88,111 @@ class dks_ue_addon_prefs(bpy.types.AddonPreferences):
8888
option_ue_json : bpy.props.BoolProperty(
8989
name="Create UE JSON",
9090
default=False,
91-
)
91+
)
92+
93+
# UE JSON Options >
94+
95+
# General
96+
97+
ue_ImportMesh : bpy.props.BoolProperty(
98+
name="Import Mesh",
99+
default=True,
100+
)
101+
ue_ImportMaterials : bpy.props.BoolProperty(
102+
name="Import Materials",
103+
default=True,
104+
)
105+
ue_ImportAnimations : bpy.props.BoolProperty(
106+
name="Import Animations",
107+
default=True,
108+
)
109+
ue_CreatePhysicsAsset : bpy.props.BoolProperty(
110+
name="Create Physics Asset",
111+
default=True,
112+
)
113+
ue_AutoComputeLodDistances : bpy.props.BoolProperty(
114+
name="Auto Compute Lod Distances",
115+
default=True,
116+
)
117+
118+
# Static Mesh
119+
120+
ue_static_mesh_NormalImportMethod : bpy.props.EnumProperty(
121+
items=[('ComputeNormals', "ComputeNormals", "Compute Normals"),('ImportNormalsAndTangents', "ImportNormalsAndTangents", "Import Normals And Tangents"),('ImportNormals', "ImportNormals", "Import Normals"),],
122+
name="Normal Import Method",
123+
default='ComputeNormals',
124+
)
125+
ue_static_mesh_ImportMeshLODs : bpy.props.BoolProperty(
126+
name="Import Mesh LODs",
127+
default=False,
128+
)
129+
ue_static_mesh_CombineMeshes : bpy.props.BoolProperty(
130+
name="Combine Meshes",
131+
default=False,
132+
)
133+
ue_static_mesh_AutoGenerateCollision : bpy.props.BoolProperty(
134+
name="Auto Generate Collision",
135+
default=True,
136+
)
137+
138+
# Skeletal Mesh
139+
140+
ue_skeletal_mesh_NormalImportMethod : bpy.props.EnumProperty(
141+
items=[('ComputeNormals', "ComputeNormals", "Compute Normals"),('ImportNormalsAndTangents', "ImportNormalsAndTangents", "Import Normals And Tangents"),('ImportNormals', "ImportNormals", "Import Normals"),],
142+
name="Normal Import Method",
143+
default='ComputeNormals',
144+
)
145+
ue_skeletal_mesh_ImportMeshLODs : bpy.props.BoolProperty(
146+
name="Import Mesh LODs",
147+
default=False,
148+
)
149+
ue_skeletal_mesh_UseT0AsRefPose : bpy.props.BoolProperty(
150+
name="UseT0AsRefPose",
151+
default=True,
152+
)
153+
ue_skeletal_mesh_PreserveSmoothingGroups : bpy.props.BoolProperty(
154+
name="Preserve Smoothing Groups",
155+
default=True,
156+
)
157+
ue_skeletal_mesh_ImportMorphTargets : bpy.props.BoolProperty(
158+
name="Import Morph Targets",
159+
default=False,
160+
)
161+
162+
# Animations
163+
164+
ue_animation_animation_length : bpy.props.EnumProperty(
165+
items=[('AnimatedKey', "AnimatedKey", "Animated Key"),('ExportedTime', "ExportedTime", "Exported Time"),('SetRange', "SetRange", "Set Range"),],
166+
name="Animation_Length",
167+
default='ExportedTime',
168+
)
169+
ue_animation_frame_range_min : bpy.props.IntProperty(
170+
name="Frame Range Min",
171+
default=0,
172+
)
173+
ue_animation_frame_range_max : bpy.props.IntProperty(
174+
name="Frame Range Max",
175+
default=0,
176+
)
177+
ue_animation_ImportMeshesInBoneHierarchy : bpy.props.BoolProperty(
178+
name="Import Meshes In Bone Hierarchy",
179+
default=True,
180+
)
181+
ue_animation_UseDefaultSampleRate : bpy.props.BoolProperty(
182+
name="Use Default Sample Rate",
183+
default=False,
184+
)
185+
ue_animation_CustomSampleRate : bpy.props.IntProperty(
186+
name="Custom Sample Rate",
187+
default=0,
188+
)
189+
ue_animation_ConvertScene : bpy.props.BoolProperty(
190+
name="Convert Scene",
191+
default=True,
192+
)
193+
194+
# < UE JSON Options
195+
92196
def draw(self, context):
93197

94198
layout = self.layout
@@ -111,9 +215,44 @@ def draw(self, context):
111215
box.prop(self, 'option_camera_rotation')
112216
box=layout.box()
113217
box.prop(self, 'option_copy_textures')
218+
114219
box=layout.box()
115220
box.prop(self, 'option_ue_json')
116221
box.label(text='Creates a "{fbx_file_name}.bjd" for the UE Plugin.',icon='INFO')
222+
223+
box_sub=box.box()
224+
box_sub.label(text='UE JSON Settings',icon='RADIOBUT_ON')
225+
box_sub.prop(self, 'ue_ImportMesh')
226+
box_sub.prop(self, 'ue_ImportMaterials')
227+
box_sub.prop(self, 'ue_ImportAnimations')
228+
box_sub.prop(self, 'ue_CreatePhysicsAsset')
229+
box_sub.prop(self, 'ue_AutoComputeLodDistances')
230+
231+
box_sub=box.box()
232+
box_sub.label(text='Static Mesh',icon='RADIOBUT_ON')
233+
box_sub.prop(self, 'ue_static_mesh_NormalImportMethod')
234+
box_sub.prop(self, 'ue_static_mesh_ImportMeshLODs')
235+
box_sub.prop(self, 'ue_static_mesh_CombineMeshes')
236+
box_sub.prop(self, 'ue_static_mesh_AutoGenerateCollision')
237+
238+
box_sub=box.box()
239+
box_sub.label(text='Skeletal Mesh',icon='RADIOBUT_ON')
240+
box_sub.prop(self, 'ue_skeletal_mesh_NormalImportMethod')
241+
box_sub.prop(self, 'ue_skeletal_mesh_ImportMeshLODs')
242+
box_sub.prop(self, 'ue_skeletal_mesh_UseT0AsRefPose')
243+
box_sub.prop(self, 'ue_skeletal_mesh_PreserveSmoothingGroups')
244+
box_sub.prop(self, 'ue_skeletal_mesh_ImportMorphTargets')
245+
246+
box_sub=box.box()
247+
box_sub.label(text='Animations',icon='RADIOBUT_ON')
248+
box_sub.prop(self, 'ue_animation_animation_length')
249+
box_sub.prop(self, 'ue_animation_frame_range_min')
250+
box_sub.prop(self, 'ue_animation_frame_range_max')
251+
box_sub.prop(self, 'ue_animation_ImportMeshesInBoneHierarchy')
252+
box_sub.prop(self, 'ue_animation_UseDefaultSampleRate')
253+
box_sub.prop(self, 'ue_animation_CustomSampleRate')
254+
box_sub.prop(self, 'ue_animation_ConvertScene')
255+
117256

118257
class dks_ue_menu(bpy.types.Menu):
119258

dks_ue.py

Lines changed: 96 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,99 @@ def dks_ue_get_texture_file(texture_path,mesh_name,mat_name,texture_name,texture
125125
else:
126126
return ""
127127

128+
def dks_ue_create_bjd(self, context):
129+
130+
global _preferences
131+
132+
blender_data = {}
133+
134+
blender_data['path']=dks_ue_get_export_sub().replace("\\","/")
135+
136+
blender_data['options'] = {}
137+
138+
blender_data['options']['ImportMesh']=bpy.context.preferences.addons[__package__].preferences.ue_ImportMesh;
139+
blender_data['options']['ImportMaterials']=bpy.context.preferences.addons[__package__].preferences.ue_ImportMaterials;
140+
blender_data['options']['ImportAnimations']=bpy.context.preferences.addons[__package__].preferences.ue_ImportAnimations;
141+
blender_data['options']['CreatePhysicsAsset']=bpy.context.preferences.addons[__package__].preferences.ue_CreatePhysicsAsset;
142+
blender_data['options']['AutoComputeLodDistances']=bpy.context.preferences.addons[__package__].preferences.ue_AutoComputeLodDistances;
143+
144+
blender_data['options']['static_mesh']={}
145+
blender_data['options']['static_mesh']['NormalImportMethod']=bpy.context.preferences.addons[__package__].preferences.ue_static_mesh_NormalImportMethod;
146+
blender_data['options']['static_mesh']['ImportMeshLODs']=bpy.context.preferences.addons[__package__].preferences.ue_static_mesh_ImportMeshLODs;
147+
blender_data['options']['static_mesh']['CombineMeshes']=bpy.context.preferences.addons[__package__].preferences.ue_static_mesh_CombineMeshes;
148+
blender_data['options']['static_mesh']['AutoGenerateCollision']=bpy.context.preferences.addons[__package__].preferences.ue_static_mesh_AutoGenerateCollision;
149+
150+
blender_data['options']['skeletal_mesh']={}
151+
blender_data['options']['skeletal_mesh']['NormalImportMethod']=bpy.context.preferences.addons[__package__].preferences.ue_skeletal_mesh_NormalImportMethod;
152+
blender_data['options']['skeletal_mesh']['ImportMeshLODs']=bpy.context.preferences.addons[__package__].preferences.ue_skeletal_mesh_ImportMeshLODs;
153+
blender_data['options']['skeletal_mesh']['UseT0AsRefPose']=bpy.context.preferences.addons[__package__].preferences.ue_skeletal_mesh_UseT0AsRefPose;
154+
blender_data['options']['skeletal_mesh']['PreserveSmoothingGroups']=bpy.context.preferences.addons[__package__].preferences.ue_skeletal_mesh_PreserveSmoothingGroups;
155+
blender_data['options']['skeletal_mesh']['ImportMorphTargets']=bpy.context.preferences.addons[__package__].preferences.ue_skeletal_mesh_ImportMorphTargets;
156+
157+
blender_data['options']['animation']={}
158+
blender_data['options']['animation']['animation_length']=bpy.context.preferences.addons[__package__].preferences.ue_animation_animation_length;
159+
blender_data['options']['animation']['frame_range_min']=bpy.context.preferences.addons[__package__].preferences.ue_animation_frame_range_min;
160+
blender_data['options']['animation']['frame_range_max']=bpy.context.preferences.addons[__package__].preferences.ue_animation_frame_range_max;
161+
blender_data['options']['animation']['ImportMeshesInBoneHierarchy']=bpy.context.preferences.addons[__package__].preferences.ue_animation_ImportMeshesInBoneHierarchy;
162+
blender_data['options']['animation']['UseDefaultSampleRate']=bpy.context.preferences.addons[__package__].preferences.ue_animation_UseDefaultSampleRate;
163+
blender_data['options']['animation']['CustomSampleRate']=bpy.context.preferences.addons[__package__].preferences.ue_animation_CustomSampleRate;
164+
blender_data['options']['animation']['ConvertScene']=bpy.context.preferences.addons[__package__].preferences.ue_animation_ConvertScene;
165+
166+
blender_data['materials'] = []
167+
168+
if _preferences["option_copy_textures"]:
169+
170+
_objects = bpy.context.scene.objects
171+
_texture_ext="png"
172+
173+
_path_textures_from = bpy.path.abspath('//') + _preferences["option_textures_folder"] + sep
174+
_path_textures_to = dks_ue_get_export_path() + _preferences["option_textures_folder"] + sep
175+
176+
for _obj in _objects:
177+
178+
if _obj.type=='MESH':
179+
180+
_obj_name = _obj.name
181+
182+
_materials = _obj.data.materials
183+
184+
for _material in _materials:
185+
186+
_material_name = _material.name
187+
188+
_material_data = {}
189+
_material_data["name"]=_material_name
190+
191+
_file_Base_Color = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Base_Color',_texture_ext)
192+
if _file_Base_Color=="":
193+
_file_Base_Color = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'BaseColor',_texture_ext)
194+
_file_Ambient_occlusion = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Ambient_occlusion',_texture_ext)
195+
_file_Metallic = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Metallic',_texture_ext)
196+
_file_Roughness = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Roughness',_texture_ext)
197+
_file_ORM = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'OcclusionRoughnessMetallic',_texture_ext)
198+
_file_Opacity = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Opacity',_texture_ext)
199+
_file_Normal = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Normal',_texture_ext)
200+
if _file_Normal=="":
201+
_file_Normal = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Normal_OpenGL',_texture_ext)
202+
_file_Emissive = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Emissive',_texture_ext)
203+
204+
_material_data['base_color']=_file_Base_Color[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
205+
_material_data['normal']=_file_Normal[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
206+
_material_data['orm']=_file_ORM[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
207+
_material_data['opacity']=_file_Opacity[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
208+
_material_data['ambient_occlusion']=_file_Ambient_occlusion[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
209+
_material_data['metallic']=_file_Metallic[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
210+
_material_data['roughness']=_file_Roughness[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
211+
_material_data['emissive']=_file_Emissive[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
212+
213+
blender_data['materials'].append(_material_data)
214+
215+
json_data = json.dumps(blender_data, sort_keys=False, indent=3)
216+
json_data_filename = dks_ue_filename().replace(".fbx",".bjd")
217+
218+
with open(json_data_filename, 'w') as f:
219+
json.dump(blender_data, f)
220+
128221
class dks_ue_export(bpy.types.Operator):
129222

130223
bl_idname = "dks_ue.export"
@@ -217,63 +310,9 @@ def execute(self, context):
217310
if path.exists(_path_textures_from):
218311
dir_util.copy_tree(_path_textures_from, _path_textures_to)
219312

220-
blender_data = {}
221-
blender_data['path']=dks_ue_get_export_sub().replace("\\","/")
222-
blender_data['options'] = {}
223-
224-
blender_data['options']['ImportMaterials']=True;
225-
blender_data['options']['ImportAnimations']=True;
226-
blender_data['options']['CreatePhysicsAsset']=True;
227-
228-
blender_data['materials'] = []
229-
230-
_objects = bpy.context.scene.objects
231-
_texture_ext="png"
232-
233-
for _obj in _objects:
234-
235-
if _obj.type=='MESH':
236-
237-
_obj_name = _obj.name
238-
239-
_materials = _obj.data.materials
240-
241-
for _material in _materials:
242-
243-
_material_name = _material.name
244-
245-
_material_data = {}
246-
_material_data["name"]=_material_name
247-
248-
_file_Base_Color = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Base_Color',_texture_ext)
249-
if _file_Base_Color=="":
250-
_file_Base_Color = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'BaseColor',_texture_ext)
251-
_file_Ambient_occlusion = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Ambient_occlusion',_texture_ext)
252-
_file_Metallic = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Metallic',_texture_ext)
253-
_file_Roughness = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Roughness',_texture_ext)
254-
_file_ORM = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'OcclusionRoughnessMetallic',_texture_ext)
255-
_file_Opacity = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Opacity',_texture_ext)
256-
_file_Normal = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Normal',_texture_ext)
257-
if _file_Normal=="":
258-
_file_Normal = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Normal_OpenGL',_texture_ext)
259-
_file_Emissive = dks_ue_get_texture_file(_path_textures_from,_obj_name,_material_name,'Emissive',_texture_ext)
260-
261-
_material_data['base_color']=_file_Base_Color[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
262-
_material_data['normal']=_file_Normal[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
263-
_material_data['orm']=_file_ORM[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
264-
_material_data['opacity']=_file_Opacity[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
265-
_material_data['ambient_occlusion']=_file_Ambient_occlusion[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
266-
_material_data['metallic']=_file_Metallic[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
267-
_material_data['roughness']=_file_Roughness[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
268-
_material_data['emissive']=_file_Emissive[len(bpy.path.abspath('//')):].replace("\\","/").replace("."+_texture_ext,"")
269-
270-
blender_data['materials'].append(_material_data)
271-
272-
json_data = json.dumps(blender_data, sort_keys=False, indent=3)
273-
json_data_filename = dks_ue_filename().replace(".fbx",".bjd")
274-
275-
with open(json_data_filename, 'w') as f:
276-
json.dump(blender_data, f)
313+
if _preferences["option_ue_json"]:
314+
315+
dks_ue_create_bjd(self, context)
277316

278317
return {'FINISHED'}
279318

screenshots/ue_prefs_ue.png

84.7 KB
Loading

0 commit comments

Comments
 (0)