Merge branch 'feature-wysiwyg'
This commit is contained in:
@@ -12,6 +12,7 @@ class ASEBuilderError(Exception):
|
|||||||
class ASEBuilderOptions(object):
|
class ASEBuilderOptions(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.scale = 1.0
|
self.scale = 1.0
|
||||||
|
self.use_raw_mesh_data = False
|
||||||
|
|
||||||
|
|
||||||
class ASEBuilder(object):
|
class ASEBuilder(object):
|
||||||
@@ -19,17 +20,29 @@ class ASEBuilder(object):
|
|||||||
ase = ASE()
|
ase = ASE()
|
||||||
|
|
||||||
main_geometry_object = None
|
main_geometry_object = None
|
||||||
for obj in context.selected_objects:
|
for selected_object in context.selected_objects:
|
||||||
if obj is None or obj.type != 'MESH':
|
if selected_object is None or selected_object.type != 'MESH':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
mesh_data = obj.data
|
# Evaluate the mesh after modifiers are applied
|
||||||
|
if options.use_raw_mesh_data:
|
||||||
|
mesh_object = selected_object
|
||||||
|
mesh_data = mesh_object.data
|
||||||
|
else:
|
||||||
|
depsgraph = context.evaluated_depsgraph_get()
|
||||||
|
bm = bmesh.new()
|
||||||
|
bm.from_object(selected_object, depsgraph)
|
||||||
|
mesh_data = bpy.data.meshes.new('')
|
||||||
|
bm.to_mesh(mesh_data)
|
||||||
|
del bm
|
||||||
|
mesh_object = bpy.data.objects.new('', mesh_data)
|
||||||
|
mesh_object.matrix_world = selected_object.matrix_world
|
||||||
|
|
||||||
if not is_collision_name(obj.name) and main_geometry_object is not None:
|
if not is_collision_name(selected_object.name) and main_geometry_object is not None:
|
||||||
geometry_object = main_geometry_object
|
geometry_object = main_geometry_object
|
||||||
else:
|
else:
|
||||||
geometry_object = ASEGeometryObject()
|
geometry_object = ASEGeometryObject()
|
||||||
geometry_object.name = obj.name
|
geometry_object.name = selected_object.name
|
||||||
if not geometry_object.is_collision:
|
if not geometry_object.is_collision:
|
||||||
main_geometry_object = geometry_object
|
main_geometry_object = geometry_object
|
||||||
ase.geometry_objects.append(geometry_object)
|
ase.geometry_objects.append(geometry_object)
|
||||||
@@ -37,25 +50,27 @@ class ASEBuilder(object):
|
|||||||
if geometry_object.is_collision:
|
if geometry_object.is_collision:
|
||||||
# Test that collision meshes are manifold and convex.
|
# Test that collision meshes are manifold and convex.
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
bm.from_mesh(obj.data)
|
bm.from_mesh(mesh_object.data)
|
||||||
for edge in bm.edges:
|
for edge in bm.edges:
|
||||||
if not edge.is_manifold:
|
if not edge.is_manifold:
|
||||||
raise ASEBuilderError(f'Collision mesh \'{obj.name}\' is not manifold')
|
del bm
|
||||||
|
raise ASEBuilderError(f'Collision mesh \'{selected_object.name}\' is not manifold')
|
||||||
if not edge.is_convex:
|
if not edge.is_convex:
|
||||||
raise ASEBuilderError(f'Collision mesh \'{obj.name}\' is not convex')
|
del bm
|
||||||
|
raise ASEBuilderError(f'Collision mesh \'{selected_object.name}\' is not convex')
|
||||||
|
|
||||||
if not geometry_object.is_collision and len(mesh_data.materials) == 0:
|
if not geometry_object.is_collision and len(selected_object.data.materials) == 0:
|
||||||
raise ASEBuilderError(f'Mesh \'{obj.name}\' must have at least one material')
|
raise ASEBuilderError(f'Mesh \'{selected_object.name}\' must have at least one material')
|
||||||
|
|
||||||
vertex_transform = Matrix.Scale(options.scale, 4) @ Matrix.Rotation(math.pi, 4, 'Z') @ obj.matrix_world
|
vertex_transform = Matrix.Scale(options.scale, 4) @ Matrix.Rotation(math.pi, 4, 'Z') @ mesh_object.matrix_world
|
||||||
for vertex_index, vertex in enumerate(mesh_data.vertices):
|
for vertex_index, vertex in enumerate(mesh_data.vertices):
|
||||||
geometry_object.vertices.append(vertex_transform @ vertex.co)
|
geometry_object.vertices.append(vertex_transform @ vertex.co)
|
||||||
|
|
||||||
material_indices = []
|
material_indices = []
|
||||||
if not geometry_object.is_collision:
|
if not geometry_object.is_collision:
|
||||||
for mesh_material_index, material in enumerate(mesh_data.materials):
|
for mesh_material_index, material in enumerate(selected_object.data.materials):
|
||||||
if material is None:
|
if material is None:
|
||||||
raise ASEBuilderError(f'Material slot {mesh_material_index + 1} for mesh \'{obj.name}\' cannot be empty')
|
raise ASEBuilderError(f'Material slot {mesh_material_index + 1} for mesh \'{selected_object.name}\' cannot be empty')
|
||||||
try:
|
try:
|
||||||
# Reuse existing material entries for duplicates
|
# Reuse existing material entries for duplicates
|
||||||
material_index = ase.materials.index(material.name)
|
material_index = ase.materials.index(material.name)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class ASE_OT_ExportOperator(bpy.types.Operator, bpy_extras.io_utils.ExportHelper
|
|||||||
('U', 'Unreal', '')),
|
('U', 'Unreal', '')),
|
||||||
name='Units'
|
name='Units'
|
||||||
)
|
)
|
||||||
|
use_raw_mesh_data: BoolProperty(default=False, name='Raw Mesh Data')
|
||||||
|
|
||||||
units_scale = {
|
units_scale = {
|
||||||
'M': 60.352,
|
'M': 60.352,
|
||||||
@@ -33,10 +34,12 @@ class ASE_OT_ExportOperator(bpy.types.Operator, bpy_extras.io_utils.ExportHelper
|
|||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.prop(self, 'units', expand=False)
|
layout.prop(self, 'units', expand=False)
|
||||||
|
layout.prop(self, 'use_raw_mesh_data')
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
options = ASEBuilderOptions()
|
options = ASEBuilderOptions()
|
||||||
options.scale = self.units_scale[self.units]
|
options.scale = self.units_scale[self.units]
|
||||||
|
options.use_raw_mesh_data = self.use_raw_mesh_data
|
||||||
try:
|
try:
|
||||||
ase = ASEBuilder().build(context, options)
|
ase = ASEBuilder().build(context, options)
|
||||||
ASEWriter().write(self.filepath, ase)
|
ASEWriter().write(self.filepath, ase)
|
||||||
|
|||||||
Reference in New Issue
Block a user