forked from LeenkxTeam/LNXSDK
Repe [T3DU] Update - 31f26d171bba0355ce2a77031e3aad4c64dbc7e9
This commit is contained in:
@ -64,13 +64,14 @@ class NodeType(Enum):
|
||||
SPEAKER = 5
|
||||
DECAL = 6
|
||||
PROBE = 7
|
||||
CURVE = 8
|
||||
|
||||
@classmethod
|
||||
def get_bobject_type(cls, bobject: bpy.types.Object) -> "NodeType":
|
||||
"""Returns the NodeType enum member belonging to the type of
|
||||
the given blender object."""
|
||||
if bobject.type == "MESH":
|
||||
if bobject.data.polygons or bobject.data.edges or bobject.data.vertices:
|
||||
if bobject.data.polygons: #or bobject.data.edges or bobject.data.vertices:
|
||||
return cls.MESH
|
||||
elif bobject.type in ('FONT', 'META', 'CURVE'): # FIXME: curves with meshes shouldn't be used in modifiers for now.
|
||||
if bobject.type == 'CURVE':
|
||||
@ -89,12 +90,14 @@ class NodeType(Enum):
|
||||
return cls.SPEAKER
|
||||
elif bobject.type == "LIGHT_PROBE":
|
||||
return cls.PROBE
|
||||
elif bobject.type == "CURVE":
|
||||
return cls.CURVE
|
||||
return cls.EMPTY
|
||||
|
||||
|
||||
STRUCT_IDENTIFIER = ("object", "bone_object", "mesh_object",
|
||||
"light_object", "camera_object", "speaker_object",
|
||||
"decal_object", "probe_object")
|
||||
"decal_object", "probe_object", "curve_object")
|
||||
|
||||
# Internal target names for single FCurve data paths
|
||||
FCURVE_TARGET_NAMES = {
|
||||
@ -161,6 +164,7 @@ class LeenkxExporter:
|
||||
self.bobject_array: Dict[bpy.types.Object, Dict[str, Union[NodeType, str]]] = {}
|
||||
self.bobject_bone_array = {}
|
||||
self.mesh_array = {}
|
||||
self.curve_array = {}
|
||||
self.light_array = {}
|
||||
self.probe_array = {}
|
||||
self.camera_array = {}
|
||||
@ -405,7 +409,7 @@ class LeenkxExporter:
|
||||
o['transform'] = {'values': LeenkxExporter.write_matrix(matrix_local)}
|
||||
|
||||
# Animated transform
|
||||
if bobject.animation_data is not None and bobject.type != "ARMATURE":
|
||||
if bobject.animation_data is not None and bobject.type != "ARMATURE" and bobject.lnx_animation_enabled:
|
||||
action = bobject.animation_data.action
|
||||
|
||||
if action is not None:
|
||||
@ -987,7 +991,7 @@ class LeenkxExporter:
|
||||
|
||||
out_object = self.object_to_lnx_object_dict[bobject]
|
||||
out_object['type'] = STRUCT_IDENTIFIER[object_type.value]
|
||||
out_object['name'] = bobject_ref["structName"]
|
||||
out_object['name'] = lnx.utils.safestr(bobject_ref["structName"])
|
||||
|
||||
if bobject.parent_type == "BONE":
|
||||
out_object['parent_bone'] = bobject.parent_bone
|
||||
@ -1064,7 +1068,7 @@ class LeenkxExporter:
|
||||
_num_verts = len(_verts)
|
||||
_all_co = np.empty(_num_verts * 3, dtype='<f8')
|
||||
_verts.foreach_get('co', _all_co)
|
||||
_all_str = _all_co.astype('U32').tolist()
|
||||
_all_f = _all_co.tolist()
|
||||
_num_groups = len(bobject.vertex_groups)
|
||||
_vg_idx = [[] for _ in range(_num_groups)]
|
||||
for v in _verts:
|
||||
@ -1079,9 +1083,9 @@ class LeenkxExporter:
|
||||
_values = []
|
||||
for vi in indices:
|
||||
base = vi * 3
|
||||
_values.append(_all_str[base])
|
||||
_values.append(_all_str[base + 1])
|
||||
_values.append(_all_str[base + 2])
|
||||
_values.append(_all_f[base])
|
||||
_values.append(_all_f[base + 1])
|
||||
_values.append(_all_f[base + 2])
|
||||
else:
|
||||
_values = []
|
||||
out_object['vertex_groups'].append({
|
||||
@ -1100,16 +1104,24 @@ class LeenkxExporter:
|
||||
if len(bobject.lnx_propertylist) > 0:
|
||||
out_object['properties'] = []
|
||||
for proplist_item in bobject.lnx_propertylist:
|
||||
# Check if the property is a collection (array type).
|
||||
if proplist_item.type_prop == 'array':
|
||||
# Convert the collection to a list.
|
||||
|
||||
array_type = proplist_item.array_item_type
|
||||
collection_value = getattr(proplist_item, 'array_prop')
|
||||
property_name = array_type + '_prop'
|
||||
value = [str(getattr(item, property_name)) for item in collection_value]
|
||||
|
||||
if array_type == 'vector':
|
||||
value = []
|
||||
for item in collection_value:
|
||||
v = getattr(item, property_name)
|
||||
value.append([float(v[0]), float(v[1]), float(v[2])])
|
||||
else:
|
||||
value = [getattr(item, property_name) for item in collection_value]
|
||||
|
||||
elif proplist_item.type_prop == 'vector':
|
||||
v = getattr(proplist_item, 'vector_prop')
|
||||
value = [float(v[0]), float(v[1]), float(v[2])]
|
||||
|
||||
else:
|
||||
# Handle other types of properties.
|
||||
value = getattr(proplist_item, proplist_item.type_prop + '_prop')
|
||||
|
||||
out_property = {
|
||||
@ -1163,6 +1175,9 @@ class LeenkxExporter:
|
||||
# Decal flag
|
||||
if mat is not None and mat.lnx_decal:
|
||||
out_object['type'] = 'decal_object'
|
||||
if mat is not None:
|
||||
if 'Rot' in bobject.lnx_instanced:
|
||||
mat.lnx_instanced_rot_type = bobject.lnx_instanced_rot_type
|
||||
# No material, mimic cycles and assign default
|
||||
if len(out_object['material_refs']) == 0:
|
||||
self.use_default_material(bobject, out_object)
|
||||
@ -1228,15 +1243,32 @@ class LeenkxExporter:
|
||||
self.speaker_array[objref]["objectTable"].append(bobject)
|
||||
out_object['data_ref'] = self.speaker_array[objref]["structName"]
|
||||
|
||||
elif object_type is NodeType.CURVE:
|
||||
if objref not in self.curve_array:
|
||||
self.curve_array[objref] = {"structName" : objname, "objectTable" : [bobject]}
|
||||
else:
|
||||
self.curve_array[objref]["objectTable"].append(bobject)
|
||||
out_object['data_ref'] = lnx.utils.safestr(self.curve_array[objref]["structName"])
|
||||
|
||||
out_object['material_refs'] = []
|
||||
for i in range(len(bobject.material_slots)):
|
||||
mat = self.slot_to_material(bobject, bobject.material_slots[i])
|
||||
# Export ref
|
||||
self.export_material_ref(bobject, mat, i, out_object)
|
||||
# Decal flag
|
||||
if mat is not None and mat.lnx_decal:
|
||||
out_object['type'] = 'decal_object'
|
||||
|
||||
|
||||
# Export the transform. If object is animated, then animation tracks are exported here
|
||||
if bobject.type != 'ARMATURE' and bobject.animation_data is not None:
|
||||
action = bobject.animation_data.action
|
||||
export_actions = [action]
|
||||
for track in bobject.animation_data.nla_tracks:
|
||||
if track.strips is None:
|
||||
if track.strips is None or track.mute:
|
||||
continue
|
||||
for strip in track.strips:
|
||||
if strip.action is None or strip.action in export_actions:
|
||||
if strip.action is None or strip.action in export_actions or strip.mute:
|
||||
continue
|
||||
export_actions.append(strip.action)
|
||||
orig_action = action
|
||||
@ -1265,7 +1297,7 @@ class LeenkxExporter:
|
||||
bone_translation_pose = pose_bone.tail - pose_bone.head
|
||||
out_object['parent_bone_tail_pose'] = [bone_translation_pose[0], bone_translation_pose[1], bone_translation_pose[2]]
|
||||
|
||||
if bobject.type == 'ARMATURE' and bobject.data is not None:
|
||||
if lnx.utils.get_rp().lnx_skin != 'Off' and bobject.type == 'ARMATURE' and bobject.data is not None:
|
||||
# Armature data
|
||||
bdata = bobject.data
|
||||
# Reference start action
|
||||
@ -1290,10 +1322,10 @@ class LeenkxExporter:
|
||||
# armature object to deform with
|
||||
if hasattr(adata, 'nla_tracks') and adata.nla_tracks is not None:
|
||||
for track in adata.nla_tracks:
|
||||
if track.strips is None:
|
||||
if track.strips is None or track.mute:
|
||||
continue
|
||||
for strip in track.strips:
|
||||
if strip.action is None:
|
||||
if strip.action is None or strip.mute:
|
||||
continue
|
||||
if strip.action.name == action.name:
|
||||
continue
|
||||
@ -2196,6 +2228,86 @@ class LeenkxExporter:
|
||||
except ReferenceError:
|
||||
pass
|
||||
|
||||
def export_curve(self, object_ref):
|
||||
"""Exports a single curve object."""
|
||||
table = object_ref[1]["objectTable"]
|
||||
bobject = table[0]
|
||||
curve_id = lnx.utils.safestr(object_ref[1]["structName"])
|
||||
|
||||
world = bpy.data.worlds['Lnx']
|
||||
if world.lnx_verbose_output:
|
||||
print('Exporting curve ' + lnx.utils.asset_name(bobject.data))
|
||||
|
||||
curve_data = bobject.data
|
||||
|
||||
out_curve = {
|
||||
'name': curve_id,
|
||||
'object': bobject.name,
|
||||
'splines': [],
|
||||
'strength': curve_data.lnx_draw_strength,
|
||||
'color': [curve_data.lnx_draw_color[0], curve_data.lnx_draw_color[1], curve_data.lnx_draw_color[2], curve_data.lnx_draw_color[3]]
|
||||
}
|
||||
|
||||
for spline in curve_data.splines:
|
||||
if spline.type == 'BEZIER':
|
||||
current_spline = {
|
||||
'closed': spline.use_cyclic_u,
|
||||
'resolution': spline.resolution_u,
|
||||
'points': [],
|
||||
'material_index': spline.material_index,
|
||||
}
|
||||
|
||||
for bezier_point in spline.bezier_points:
|
||||
point_data = {
|
||||
'co': [bezier_point.co.x, bezier_point.co.y, bezier_point.co.z],
|
||||
'handle_left': [bezier_point.handle_left.x, bezier_point.handle_left.y, bezier_point.handle_left.z],
|
||||
'handle_right': [bezier_point.handle_right.x, bezier_point.handle_right.y, bezier_point.handle_right.z]
|
||||
}
|
||||
current_spline['points'].append(point_data)
|
||||
|
||||
out_curve['splines'].append(current_spline)
|
||||
|
||||
active_keys = [kb for kb in bobject.data.shape_keys.key_blocks if not kb.mute] if bobject.data.shape_keys else []
|
||||
|
||||
if len(active_keys) == 0:
|
||||
temp_obj = bobject.to_mesh()
|
||||
|
||||
if len(temp_obj.polygons) > 0:
|
||||
temp_ref = [object_ref[0], {
|
||||
"objectTable": table,
|
||||
"structName": lnx.utils.safestr(curve_id)
|
||||
}]
|
||||
|
||||
self.export_mesh(temp_ref)
|
||||
|
||||
bobject.to_mesh_clear()
|
||||
else:
|
||||
out_curve['shape_keys'] = []
|
||||
for kb in bobject.data.shape_keys.key_blocks:
|
||||
key_data = {
|
||||
'name': kb.name,
|
||||
'value': kb.value,
|
||||
'points': []
|
||||
}
|
||||
for p in kb.data:
|
||||
key_data['points'].append({
|
||||
'co': p.co[:],
|
||||
'handle_left': p.handle_left[:],
|
||||
'handle_right': p.handle_right[:]
|
||||
})
|
||||
out_curve['shape_keys'].append(key_data)
|
||||
|
||||
mat_count = len(bobject.material_slots)
|
||||
if mat_count > 0:
|
||||
out_curve['material_refs'] = []
|
||||
for i in range(mat_count):
|
||||
mat = self.slot_to_material(bobject, bobject.material_slots[i])
|
||||
self.export_material_ref(bobject, mat, i, out_curve)
|
||||
|
||||
self.output['curve_datas'].append(out_curve)
|
||||
|
||||
|
||||
|
||||
def export_light(self, object_ref):
|
||||
"""Exports a single light object."""
|
||||
rpdat = lnx.utils.get_rp()
|
||||
@ -2288,11 +2400,11 @@ class LeenkxExporter:
|
||||
o = {'name': objectRef[1]["structName"]}
|
||||
bo = objectRef[0]
|
||||
|
||||
if bo.type == 'GRID':
|
||||
if bo.type in ('GRID', 'VOLUME'):
|
||||
o['type'] = 'grid'
|
||||
elif bo.type == 'PLANAR':
|
||||
elif bo.type in ('PLANAR', 'PLANE'):
|
||||
o['type'] = 'planar'
|
||||
else:
|
||||
else: # (CUBEMAP, SPHERE)
|
||||
o['type'] = 'cubemap'
|
||||
|
||||
self.output['probe_datas'].append(o)
|
||||
@ -2348,6 +2460,7 @@ class LeenkxExporter:
|
||||
if bobject.type == 'CAMERA':
|
||||
self.output['camera_ref'] = asset_name
|
||||
self.has_spawning_camera = True
|
||||
asset_name = bobject.name
|
||||
|
||||
out_collection['object_refs'].append(asset_name)
|
||||
|
||||
@ -2731,7 +2844,7 @@ class LeenkxExporter:
|
||||
'lifetime_random': psettings.lifetime_random,
|
||||
'emit_from': emit_from,
|
||||
# Velocity
|
||||
# 'normal_factor': psettings.normal_factor,
|
||||
'normal_factor': psettings.normal_factor,
|
||||
# 'tangent_factor': psettings.tangent_factor,
|
||||
# 'tangent_phase': psettings.tangent_phase,
|
||||
'object_align_factor': (
|
||||
@ -2815,20 +2928,19 @@ class LeenkxExporter:
|
||||
|
||||
def export_world(self):
|
||||
"""Exports the world of the current scene."""
|
||||
world = self.scene.world
|
||||
for world in bpy.data.worlds:
|
||||
if world is not None:
|
||||
world_name = lnx.utils.safestr(lnx.utils.asset_name(world) if world.library else world.name)
|
||||
|
||||
if world is not None:
|
||||
world_name = lnx.utils.safestr(lnx.utils.asset_name(world) if world.library else world.name)
|
||||
if world_name not in self.world_array:
|
||||
self.world_array.append(world_name)
|
||||
out_world = {'name': world_name}
|
||||
|
||||
if world_name not in self.world_array:
|
||||
self.world_array.append(world_name)
|
||||
out_world = {'name': world_name}
|
||||
self.post_export_world(world, out_world)
|
||||
self.output['world_datas'].append(out_world)
|
||||
|
||||
self.post_export_world(world, out_world)
|
||||
self.output['world_datas'].append(out_world)
|
||||
|
||||
elif lnx.utils.get_rp().rp_background == 'World':
|
||||
log.warn(f'Scene "{self.scene.name}" is missing a world, some render targets will not be cleared')
|
||||
elif lnx.utils.get_rp().rp_background == 'World':
|
||||
log.warn(f'Scene "{self.scene.name}" is missing a world, some render targets will not be cleared')
|
||||
|
||||
def export_objects(self, scene):
|
||||
"""Exports all supported blender objects.
|
||||
@ -2847,6 +2959,7 @@ class LeenkxExporter:
|
||||
self.output['light_datas'] = []
|
||||
self.output['camera_datas'] = []
|
||||
self.output['speaker_datas'] = []
|
||||
self.output['curve_datas'] = []
|
||||
|
||||
for light_ref in self.light_array.items():
|
||||
self.export_light(light_ref)
|
||||
@ -2867,6 +2980,9 @@ class LeenkxExporter:
|
||||
for lightprobe_object in self.probe_array.items():
|
||||
self.export_probe(lightprobe_object)
|
||||
|
||||
for curve_ref in self.curve_array.items():
|
||||
self.export_curve(curve_ref)
|
||||
|
||||
self.output['mesh_datas'] = []
|
||||
for mesh_ref in self.mesh_array.items():
|
||||
self.export_mesh(mesh_ref)
|
||||
@ -2896,9 +3012,9 @@ class LeenkxExporter:
|
||||
self.process_bobject(bobject)
|
||||
# Softbody needs connected triangles, use optimized
|
||||
# geometry export
|
||||
for mod in bobject.modifiers:
|
||||
"""for mod in bobject.modifiers:
|
||||
if mod.type in ('CLOTH', 'SOFT_BODY'):
|
||||
LeenkxExporter.optimize_enabled = True
|
||||
LeenkxExporter.optimize_enabled = True"""
|
||||
|
||||
self.process_skinned_meshes()
|
||||
|
||||
@ -3029,6 +3145,8 @@ class LeenkxExporter:
|
||||
|
||||
self.export_scene_traits()
|
||||
|
||||
self.export_scene_properties()
|
||||
|
||||
self.export_canvas_themes()
|
||||
|
||||
# Write embedded data references
|
||||
@ -3145,6 +3263,14 @@ class LeenkxExporter:
|
||||
instanced_type = 4
|
||||
instanced_data = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]
|
||||
|
||||
attr_data_block = []
|
||||
for attr in bobject.lnx_instanced_attrs:
|
||||
attr_data_block.extend([0.0] * attr.size)
|
||||
instanced_data.extend(attr_data_block)
|
||||
|
||||
if lnx.utils.export_morph_targets(bobject):
|
||||
instanced_data.extend([0.0, 0.0, 0.0, 0.0])
|
||||
|
||||
for child in bobject.children:
|
||||
if not child.lnx_export or child.hide_render:
|
||||
continue
|
||||
@ -3163,6 +3289,9 @@ class LeenkxExporter:
|
||||
instanced_data.append(scale.x)
|
||||
instanced_data.append(scale.y)
|
||||
instanced_data.append(scale.z)
|
||||
instanced_data.extend(attr_data_block)
|
||||
if lnx.utils.export_morph_targets(child):
|
||||
instanced_data.extend([0.0, 0.0, 0.0, 0.0])
|
||||
break
|
||||
|
||||
# Instance render collections with same children?
|
||||
@ -3338,9 +3467,9 @@ class LeenkxExporter:
|
||||
# Phys traits
|
||||
if phys_enabled:
|
||||
for modifier in bobject.modifiers:
|
||||
if modifier.type in ('CLOTH', 'SOFT_BODY'):
|
||||
if modifier.type in ('CLOTH', 'SOFT_BODY') and modifier.show_render:
|
||||
self.add_softbody_mod(o, bobject, modifier)
|
||||
elif modifier.type == 'HOOK':
|
||||
elif modifier.type == 'HOOK' and modifier.show_render:
|
||||
self.add_hook_mod(o, bobject, modifier.object.name, modifier.vertex_group)
|
||||
|
||||
# Rigid body constraint
|
||||
@ -3392,7 +3521,7 @@ class LeenkxExporter:
|
||||
if bone:
|
||||
out_constraint['bone'] = bobject.name
|
||||
if hasattr(constraint, 'target') and constraint.target is not None:
|
||||
if constraint.type == 'COPY_LOCATION':
|
||||
if constraint.type in ('COPY_LOCATION', 'COPY_ROTATION'):
|
||||
out_constraint['target'] = constraint.target.name
|
||||
out_constraint['use_x'] = constraint.use_x
|
||||
out_constraint['use_y'] = constraint.use_y
|
||||
@ -3402,9 +3531,38 @@ class LeenkxExporter:
|
||||
out_constraint['invert_z'] = constraint.invert_z
|
||||
out_constraint['use_offset'] = constraint.use_offset
|
||||
out_constraint['influence'] = constraint.influence
|
||||
elif constraint.type in ('COPY_SCALE'):
|
||||
out_constraint['target'] = constraint.target.name
|
||||
out_constraint['use_x'] = constraint.use_x
|
||||
out_constraint['use_y'] = constraint.use_y
|
||||
out_constraint['use_z'] = constraint.use_z
|
||||
out_constraint['use_offset'] = constraint.use_offset
|
||||
out_constraint['influence'] = constraint.influence
|
||||
elif constraint.type == 'COPY_TRANSFORMS':
|
||||
out_constraint['target'] = constraint.target.name
|
||||
out_constraint['influence'] = constraint.influence
|
||||
elif constraint.type == 'CHILD_OF':
|
||||
out_constraint['target'] = constraint.target.name
|
||||
out_constraint['influence'] = constraint.influence
|
||||
elif constraint.type in ('LIMIT_LOCATION', 'LIMIT_ROTATION', 'LIMIT_SCALE'):
|
||||
if constraint.type == 'LIMIT_ROTATION':
|
||||
out_constraint['use_limit_x'] = constraint.use_limit_x
|
||||
out_constraint['use_limit_y'] = constraint.use_limit_y
|
||||
out_constraint['use_limit_z'] = constraint.use_limit_z
|
||||
else:
|
||||
out_constraint['use_min_x'] = constraint.use_min_x
|
||||
out_constraint['use_min_y'] = constraint.use_min_y
|
||||
out_constraint['use_min_z'] = constraint.use_min_z
|
||||
out_constraint['use_max_x'] = constraint.use_max_x
|
||||
out_constraint['use_max_y'] = constraint.use_max_y
|
||||
out_constraint['use_max_z'] = constraint.use_max_z
|
||||
out_constraint['min_x'] = constraint.min_x
|
||||
out_constraint['min_y'] = constraint.min_y
|
||||
out_constraint['min_z'] = constraint.min_z
|
||||
out_constraint['max_x'] = constraint.max_x
|
||||
out_constraint['max_y'] = constraint.max_y
|
||||
out_constraint['max_z'] = constraint.max_z
|
||||
out_constraint['influence'] = constraint.influence
|
||||
|
||||
o['constraints'].append(out_constraint)
|
||||
|
||||
@ -3632,6 +3790,35 @@ class LeenkxExporter:
|
||||
for out_trait in self.output['traits']:
|
||||
LeenkxExporter.import_traits.append(out_trait['class_name'])
|
||||
|
||||
def export_scene_properties(self) -> None:
|
||||
bscene = self.scene
|
||||
if len(bscene.lnx_propertylist) > 0:
|
||||
if 'properties' not in self.output:
|
||||
self.output['properties'] = []
|
||||
|
||||
for proplist_item in bscene.lnx_propertylist:
|
||||
if proplist_item.type_prop == 'array':
|
||||
array_type = proplist_item.array_item_type
|
||||
collection_value = getattr(proplist_item, 'array_prop')
|
||||
property_name = array_type + '_prop'
|
||||
|
||||
if array_type == 'vector':
|
||||
value = [[v for v in getattr(item, property_name)] for item in collection_value]
|
||||
else:
|
||||
value = [getattr(item, property_name) for item in collection_value]
|
||||
|
||||
elif proplist_item.type_prop == 'vector':
|
||||
value = [v for v in getattr(proplist_item, 'vector_prop')]
|
||||
|
||||
else:
|
||||
value = getattr(proplist_item, proplist_item.type_prop + '_prop')
|
||||
|
||||
out_property = {
|
||||
'name': proplist_item.name_prop,
|
||||
'value': value
|
||||
}
|
||||
self.output['properties'].append(out_property)
|
||||
|
||||
@staticmethod
|
||||
def export_canvas_themes():
|
||||
path_themes = os.path.join(lnx.utils.get_fp(), 'Bundled', 'canvas')
|
||||
@ -3657,16 +3844,21 @@ class LeenkxExporter:
|
||||
# ClothModifier
|
||||
if modifier.type == 'CLOTH':
|
||||
bend = modifier.settings.bending_stiffness
|
||||
friction = bobject.lnx_soft_body_friction
|
||||
damping = bobject.lnx_soft_body_damping
|
||||
soft_type = 0
|
||||
# SoftBodyModifier
|
||||
elif modifier.type == 'SOFT_BODY':
|
||||
bend = (modifier.settings.bend + 1.0) * 10
|
||||
bend = modifier.settings.bend
|
||||
friction = modifier.settings.friction
|
||||
damping = modifier.settings.goal_friction
|
||||
soft_type = 1
|
||||
else:
|
||||
# Wrong modifier type
|
||||
return
|
||||
|
||||
out_trait['parameters'] = [str(soft_type), str(bend), str(modifier.settings.mass), str(bobject.lnx_soft_body_margin)]
|
||||
out_trait['parameters'] = [str(soft_type), str(bend), str(modifier.settings.mass), str(bobject.lnx_soft_body_margin), str(friction), str(damping),
|
||||
str(bobject.lnx_soft_body_linear_stiffness), str(bobject.lnx_soft_body_angular_stiffness), str(bobject.lnx_soft_body_pressure)]
|
||||
o['traits'].append(out_trait)
|
||||
|
||||
if soft_type == 0:
|
||||
|
||||
Reference in New Issue
Block a user