mirror of https://github.com/AxioDL/metaforce.git
392 lines
21 KiB
Python
392 lines
21 KiB
Python
import bpy, struct, math
|
|
from mathutils import Quaternion
|
|
|
|
def draw(layout, context):
|
|
if bpy.context.active_object:
|
|
obj = bpy.context.active_object
|
|
layout.label(text="Widget Settings:", icon='OBJECT_DATA')
|
|
layout.prop_menu_enum(obj, 'retro_widget_type', text='Widget Type')
|
|
#layout.prop_search(obj, 'retro_widget_parent', context.scene, 'objects', text='Widget Parent')
|
|
row = layout.row(align=True)
|
|
row.prop(obj, 'retro_widget_default_visible', text='Visible')
|
|
row.prop(obj, 'retro_widget_default_active', text='Active')
|
|
row.prop(obj, 'retro_widget_cull_faces', text='Cull Faces')
|
|
layout.prop(obj, 'retro_widget_color', text='Color')
|
|
layout.prop_menu_enum(obj, 'retro_widget_model_draw_flags', text='Draw Flags')
|
|
row = layout.row(align=True)
|
|
row.prop(obj, 'retro_widget_is_worker', text='Is Worker')
|
|
if obj.retro_widget_is_worker:
|
|
row.prop(obj, 'retro_widget_worker_id', text='Worker Id')
|
|
|
|
if obj.retro_widget_type == 'RETRO_MODL':
|
|
layout.prop(obj, 'retro_model_light_mask', text='Light Mask')
|
|
elif obj.retro_widget_type == 'RETRO_PANE':
|
|
layout.prop(obj, 'retro_pane_dimensions', text='Dimensions')
|
|
layout.prop(obj, 'retro_pane_scale_center', text='Center')
|
|
elif obj.retro_widget_type == 'RETRO_TXPN':
|
|
layout.prop(obj, 'retro_pane_dimensions', text='Dimensions')
|
|
layout.prop(obj, 'retro_pane_scale_center', text='Center')
|
|
layout.prop(obj, 'retro_textpane_font_path', text='Font Path')
|
|
row = layout.row(align=True)
|
|
row.prop(obj, 'retro_textpane_word_wrap', text='Word Wrap')
|
|
row.prop(obj, 'retro_textpane_horizontal', text='Horizontal')
|
|
layout.prop(obj, 'retro_textpane_fill_color', text='Fill Color')
|
|
layout.prop(obj, 'retro_textpane_outline_color', text='Outline Color')
|
|
layout.prop(obj, 'retro_textpane_block_extent', text='Point Dimensions')
|
|
layout.prop(obj, 'retro_textpane_jp_font_path', text='JP Font Path')
|
|
layout.prop(obj, 'retro_textpane_jp_font_scale', text='JP Point Dimensions')
|
|
layout.prop_menu_enum(obj, 'retro_textpane_hjustification', text='Horizontal Justification')
|
|
layout.prop_menu_enum(obj, 'retro_textpane_vjustification', text='Vertical Justification')
|
|
elif obj.retro_widget_type == 'RETRO_TBGP':
|
|
layout.prop(obj, 'retro_tablegroup_elem_count', text='Element Count')
|
|
layout.prop(obj, 'retro_tablegroup_elem_default', text='Default Element')
|
|
layout.prop(obj, 'retro_tablegroup_wraparound', text='Wraparound')
|
|
elif obj.retro_widget_type == 'RETRO_GRUP':
|
|
layout.prop(obj, 'retro_group_default_worker', text='Default Worker')
|
|
elif obj.retro_widget_type == 'RETRO_SLGP':
|
|
row = layout.row(align=True)
|
|
row.prop(obj, 'retro_slider_min', text='Min')
|
|
row.prop(obj, 'retro_slider_max', text='Max')
|
|
layout.prop(obj, 'retro_slider_default', text='Default')
|
|
layout.prop(obj, 'retro_slider_increment', text='Increment')
|
|
elif obj.retro_widget_type == 'RETRO_ENRG':
|
|
layout.prop(obj, 'retro_energybar_texture_path', text='Energy Bar Texture Path')
|
|
elif obj.retro_widget_type == 'RETRO_METR':
|
|
layout.prop(obj, 'retro_meter_no_round_up', text='No Round Up')
|
|
layout.prop(obj, 'retro_meter_max_capacity', text='Max Capacity')
|
|
layout.prop(obj, 'retro_meter_worker_count', text='Worker Count')
|
|
elif obj.retro_widget_type == 'RETRO_LITE':
|
|
if obj.data and obj.type == 'LIGHT':
|
|
layout.prop(obj.data, 'retro_light_index', text='Index')
|
|
layout.label(text="Angular Falloff:", icon='LIGHT')
|
|
row = layout.row(align=True)
|
|
row.prop(obj.data, 'retro_light_angle_constant', text='Constant')
|
|
row.prop(obj.data, 'retro_light_angle_linear', text='Linear')
|
|
row.prop(obj.data, 'retro_light_angle_quadratic', text='Quadratic')
|
|
|
|
hjustifications = None
|
|
vjustifications = None
|
|
model_draw_flags_e = None
|
|
|
|
def recursive_cook(buffer, obj, version, path_hasher, parent_name):
|
|
buffer += struct.pack('>4s', obj.retro_widget_type[6:].encode())
|
|
buffer += obj.name.encode() + b'\0'
|
|
buffer += parent_name.encode() + b'\0'
|
|
buffer += struct.pack('>bbbbffffI',
|
|
False,
|
|
obj.retro_widget_default_visible,
|
|
obj.retro_widget_default_active,
|
|
obj.retro_widget_cull_faces,
|
|
obj.retro_widget_color[0],
|
|
obj.retro_widget_color[1],
|
|
obj.retro_widget_color[2],
|
|
obj.retro_widget_color[3],
|
|
model_draw_flags_e[obj.retro_widget_model_draw_flags])
|
|
|
|
angle = Quaternion((1.0, 0.0, 0.0), 0)
|
|
|
|
if obj.retro_widget_type == 'RETRO_CAMR':
|
|
angle = Quaternion((1.0, 0.0, 0.0), math.radians(-90.0))
|
|
aspect = bpy.context.scene.render.resolution_x / bpy.context.scene.render.resolution_y
|
|
|
|
if obj.data.type == 'PERSP':
|
|
if aspect > 1.0:
|
|
fov = math.degrees(math.atan(math.tan(obj.data.angle / 2.0) / aspect)) * 2.0
|
|
else:
|
|
fov = math.degrees(obj.data.angle)
|
|
buffer += struct.pack('>Iffff', 0, fov, aspect, obj.data.clip_start, obj.data.clip_end)
|
|
|
|
elif obj.data.type == 'ORTHO':
|
|
ortho_half = obj.data.ortho_scale / 2.0
|
|
buffer += struct.pack('>Iffffff', 1, -ortho_half, ortho_half, ortho_half / aspect,
|
|
-ortho_half / aspect, obj.data.clip_start, obj.data.clip_end)
|
|
|
|
elif obj.retro_widget_type == 'RETRO_MODL':
|
|
if len(obj.children) == 0:
|
|
raise RuntimeException('Model Widget must have a child model object')
|
|
model_obj = obj.children[0]
|
|
if model_obj.type != 'MESH':
|
|
raise RuntimeException('Model Widget must have a child MESH')
|
|
if not model_obj.data.library:
|
|
raise RuntimeException('Model Widget must have a linked library MESH')
|
|
path = bpy.path.abspath(model_obj.data.library.filepath)
|
|
path_hash = path_hasher.hashpath32(path)
|
|
buffer += struct.pack('>III', path_hash, 0, obj.retro_model_light_mask)
|
|
|
|
elif obj.retro_widget_type == 'RETRO_PANE':
|
|
buffer += struct.pack('>fffff',
|
|
obj.retro_pane_dimensions[0],
|
|
obj.retro_pane_dimensions[1],
|
|
obj.retro_pane_scale_center[0],
|
|
obj.retro_pane_scale_center[1],
|
|
obj.retro_pane_scale_center[2])
|
|
|
|
elif obj.retro_widget_type == 'RETRO_TXPN':
|
|
path_hash = path_hasher.hashpath32(obj.retro_textpane_font_path)
|
|
buffer += struct.pack('>fffffIbbIIffffffffff',
|
|
obj.retro_pane_dimensions[0],
|
|
obj.retro_pane_dimensions[1],
|
|
obj.retro_pane_scale_center[0],
|
|
obj.retro_pane_scale_center[1],
|
|
obj.retro_pane_scale_center[2],
|
|
path_hash,
|
|
obj.retro_textpane_word_wrap,
|
|
obj.retro_textpane_horizontal,
|
|
hjustifications[obj.retro_textpane_hjustification],
|
|
vjustifications[obj.retro_textpane_vjustification],
|
|
obj.retro_textpane_fill_color[0],
|
|
obj.retro_textpane_fill_color[1],
|
|
obj.retro_textpane_fill_color[2],
|
|
obj.retro_textpane_fill_color[3],
|
|
obj.retro_textpane_outline_color[0],
|
|
obj.retro_textpane_outline_color[1],
|
|
obj.retro_textpane_outline_color[2],
|
|
obj.retro_textpane_outline_color[3],
|
|
obj.retro_textpane_block_extent[0],
|
|
obj.retro_textpane_block_extent[1])
|
|
if version >= 1:
|
|
path_hash = path_hasher.hashpath32(obj.retro_textpane_jp_font_path)
|
|
buffer += struct.pack('>III',
|
|
path_hash,
|
|
obj.retro_textpane_jp_font_scale[0],
|
|
obj.retro_textpane_jp_font_scale[1])
|
|
|
|
elif obj.retro_widget_type == 'RETRO_TBGP':
|
|
buffer += struct.pack('>HHIHHbbffbfHHHH',
|
|
obj.retro_tablegroup_elem_count,
|
|
0,
|
|
0,
|
|
obj.retro_tablegroup_elem_default,
|
|
0,
|
|
obj.retro_tablegroup_wraparound,
|
|
False,
|
|
0.0,
|
|
0.0,
|
|
False,
|
|
0.0,
|
|
0,
|
|
0,
|
|
0,
|
|
0)
|
|
|
|
elif obj.retro_widget_type == 'RETRO_GRUP':
|
|
buffer += struct.pack('>Hb',
|
|
obj.retro_group_default_worker,
|
|
False)
|
|
|
|
elif obj.retro_widget_type == 'RETRO_SLGP':
|
|
buffer += struct.pack('>ffff',
|
|
obj.retro_slider_min,
|
|
obj.retro_slider_max,
|
|
obj.retro_slider_default,
|
|
obj.retro_slider_increment)
|
|
|
|
elif obj.retro_widget_type == 'RETRO_ENRG':
|
|
path_hash = path_hasher.hashpath32(obj.retro_energybar_texture_path)
|
|
buffer += struct.pack('>I', path_hash)
|
|
|
|
elif obj.retro_widget_type == 'RETRO_METR':
|
|
buffer += struct.pack('>bbII',
|
|
False,
|
|
obj.retro_meter_no_round_up,
|
|
obj.retro_meter_max_capacity,
|
|
obj.retro_meter_worker_count)
|
|
|
|
elif obj.retro_widget_type == 'RETRO_LITE':
|
|
angle = Quaternion((1.0, 0.0, 0.0), math.radians(-90.0))
|
|
type_enum = 0
|
|
constant = 1.0
|
|
linear = 0.0
|
|
quadratic = 0.0
|
|
cutoff = 0.0
|
|
if obj.data.type == 'POINT':
|
|
type_enum = 4
|
|
elif obj.data.type == 'SUN':
|
|
type_enum = 2
|
|
elif obj.data.type == 'SPOT':
|
|
type_enum = 0
|
|
cutoff = obj.data.spot_size
|
|
|
|
if obj.data.type == 'POINT' or obj.data.type == 'SPOT':
|
|
constant = obj.data.constant_coefficient
|
|
linear = obj.data.linear_coefficient
|
|
quadratic = obj.data.quadratic_coefficient
|
|
|
|
buffer += struct.pack('>IffffffI',
|
|
type_enum, constant, linear, quadratic,
|
|
obj.data.retro_light_angle_constant,
|
|
obj.data.retro_light_angle_linear,
|
|
obj.data.retro_light_angle_quadratic,
|
|
obj.data.retro_light_index)
|
|
if obj.data.type == 'SPOT':
|
|
buffer += struct.pack('>f', cutoff)
|
|
|
|
elif obj.retro_widget_type == 'RETRO_IMGP':
|
|
if obj.type != 'MESH':
|
|
raise RuntimeException('Imagepane Widget must be a MESH')
|
|
if len(obj.data.loops) < 4:
|
|
raise RuntimeException('Imagepane Widget must be a MESH with 4 verts')
|
|
if len(obj.data.uv_layers) < 1:
|
|
raise RuntimeException('Imagepane Widget must ba a MESH with a UV layer')
|
|
path_hash = 0xffffffff
|
|
if len(obj.data.materials):
|
|
material = obj.data.materials[0]
|
|
if 'Image Texture' in material.node_tree.nodes:
|
|
image_node = material.node_tree.nodes['Image Texture']
|
|
if image_node.image:
|
|
image = image_node.image
|
|
path = bpy.path.abspath(image.filepath)
|
|
path_hash = path_hasher.hashpath32(path)
|
|
|
|
buffer += struct.pack('>IIII', path_hash, 0, 0, 4)
|
|
for i in range(4):
|
|
vi = obj.data.loops[i].vertex_index
|
|
co = obj.data.vertices[vi].co
|
|
buffer += struct.pack('>fff', co[0], co[1], co[2])
|
|
|
|
buffer += struct.pack('>I', 4)
|
|
for i in range(4):
|
|
co = obj.data.uv_layers[0].data[i].uv
|
|
buffer += struct.pack('>ff', co[0], co[1])
|
|
|
|
if obj.retro_widget_is_worker:
|
|
buffer += struct.pack('>bH', True, obj.retro_widget_worker_id)
|
|
else:
|
|
buffer += struct.pack('>b', False)
|
|
|
|
angMtx = angle.to_matrix() @ obj.matrix_local.to_3x3()
|
|
buffer += struct.pack('>fffffffffffffffIH',
|
|
obj.matrix_local[0][3],
|
|
obj.matrix_local[1][3],
|
|
obj.matrix_local[2][3],
|
|
angMtx[0][0], angMtx[0][1], angMtx[0][2],
|
|
angMtx[1][0], angMtx[1][1], angMtx[1][2],
|
|
angMtx[2][0], angMtx[2][1], angMtx[2][2],
|
|
0.0, 0.0, 0.0, 0, 0)
|
|
|
|
ch_list = []
|
|
for ch in obj.children:
|
|
ch_list.append((ch.pass_index, ch.name))
|
|
for s_pair in sorted(ch_list):
|
|
ch = bpy.data.objects[s_pair[1]]
|
|
if ch.retro_widget_type != 'RETRO_NONE':
|
|
recursive_cook(buffer, ch, version, path_hasher, obj.name)
|
|
|
|
|
|
def cook(writepipebuf, version, path_hasher):
|
|
global hjustifications, vjustifications, model_draw_flags_e
|
|
hjustifications = dict((i[0], i[3]) for i in bpy.types.Object.retro_textpane_hjustification[1]['items'])
|
|
vjustifications = dict((i[0], i[3]) for i in bpy.types.Object.retro_textpane_vjustification[1]['items'])
|
|
model_draw_flags_e = dict((i[0], i[3]) for i in bpy.types.Object.retro_widget_model_draw_flags[1]['items'])
|
|
|
|
buffer = bytearray()
|
|
buffer += struct.pack('>IIII', 0, 0, 0, 0)
|
|
|
|
widget_count = 0
|
|
for obj in bpy.data.objects:
|
|
if obj.retro_widget_type != 'RETRO_NONE':
|
|
widget_count += 1
|
|
buffer += struct.pack('>I', widget_count)
|
|
|
|
for obj in bpy.data.objects:
|
|
if obj.retro_widget_type != 'RETRO_NONE' and not obj.parent:
|
|
recursive_cook(buffer, obj, version, path_hasher, 'kGSYS_DummyWidgetID')
|
|
|
|
return buffer
|
|
|
|
|
|
# Registration
|
|
def register():
|
|
frame_widget_types = [
|
|
('RETRO_NONE', 'Not a Widget', '', 0),
|
|
('RETRO_BWIG', 'Base Widget', '', 1),
|
|
('RETRO_CAMR', 'Camera', '', 2),
|
|
('RETRO_ENRG', 'Energy Bar', '', 3),
|
|
('RETRO_GRUP', 'Group', '', 4),
|
|
('RETRO_HWIG', 'Head Widget', '', 5),
|
|
('RETRO_IMGP', 'Image Pane', '', 6),
|
|
('RETRO_LITE', 'Light', '', 7),
|
|
('RETRO_MODL', 'Model', '', 8),
|
|
('RETRO_METR', 'Meter', '', 9),
|
|
('RETRO_PANE', 'Pane', '', 10),
|
|
('RETRO_SLGP', 'Slider Group', '', 11),
|
|
('RETRO_TBGP', 'Table Group', '', 12),
|
|
('RETRO_TXPN', 'Text Pane', '', 13)]
|
|
bpy.types.Object.retro_widget_type = bpy.props.EnumProperty(items=frame_widget_types, name='Retro: FRME Widget Type', default='RETRO_NONE')
|
|
model_draw_flags = [
|
|
('RETRO_SHADELESS', 'Shadeless', '', 0),
|
|
('RETRO_OPAQUE', 'Opaque', '', 1),
|
|
('RETRO_ALPHA', 'Alpha', '', 2),
|
|
('RETRO_ADDITIVE', 'Additive', '', 3),
|
|
('RETRO_ALPHA_ADDITIVE_OVERDRAW', 'Alpha Additive Overdraw', '', 4)]
|
|
bpy.types.Object.retro_widget_parent = bpy.props.StringProperty(name='Retro: FRME Widget Parent', description='Refers to internal frame widgets')
|
|
bpy.types.Object.retro_widget_use_anim_controller = bpy.props.BoolProperty(name='Retro: Use Animiation Conroller')
|
|
bpy.types.Object.retro_widget_default_visible = bpy.props.BoolProperty(name='Retro: Default Visible', description='Sets widget is visible by default')
|
|
bpy.types.Object.retro_widget_default_active = bpy.props.BoolProperty(name='Retro: Default Active', description='Sets widget is cases by default')
|
|
bpy.types.Object.retro_widget_cull_faces = bpy.props.BoolProperty(name='Retro: Cull Faces', description='Enables face culling')
|
|
bpy.types.Object.retro_widget_color = bpy.props.FloatVectorProperty(name='Retro: Color', description='Sets widget color', subtype='COLOR', size=4, min=0.0, max=1.0)
|
|
bpy.types.Object.retro_widget_model_draw_flags = bpy.props.EnumProperty(items=model_draw_flags, name='Retro: Model Draw Flags', default='RETRO_ALPHA')
|
|
bpy.types.Object.retro_widget_is_worker = bpy.props.BoolProperty(name='Retro: Is Worker Widget', default=False)
|
|
bpy.types.Object.retro_widget_worker_id = bpy.props.IntProperty(name='Retro: Worker Widget ID', min=0, default=0)
|
|
|
|
bpy.types.Object.retro_model_light_mask = bpy.props.IntProperty(name='Retro: Model Light Mask', min=0, default=0)
|
|
|
|
bpy.types.Object.retro_pane_dimensions = bpy.props.FloatVectorProperty(name='Retro: Pane Dimensions', min=0.0, size=2)
|
|
bpy.types.Object.retro_pane_scale_center = bpy.props.FloatVectorProperty(name='Retro: Scale Center', size=3)
|
|
|
|
bpy.types.Object.retro_textpane_font_path = bpy.props.StringProperty(name='Retro: Font Path')
|
|
bpy.types.Object.retro_textpane_word_wrap = bpy.props.BoolProperty(name='Retro: Word Wrap')
|
|
bpy.types.Object.retro_textpane_horizontal = bpy.props.BoolProperty(name='Retro: Horizontal', default=True)
|
|
bpy.types.Object.retro_textpane_fill_color = bpy.props.FloatVectorProperty(name='Retro: Fill Color', min=0.0, max=1.0, size=4, subtype='COLOR')
|
|
bpy.types.Object.retro_textpane_outline_color = bpy.props.FloatVectorProperty(name='Retro: Outline Color', min=0.0, max=1.0, size=4, subtype='COLOR')
|
|
bpy.types.Object.retro_textpane_block_extent = bpy.props.FloatVectorProperty(name='Retro: Block Extent', min=0.0, size=2)
|
|
bpy.types.Object.retro_textpane_jp_font_path = bpy.props.StringProperty(name='Retro: Japanese Font Path')
|
|
bpy.types.Object.retro_textpane_jp_font_scale = bpy.props.IntVectorProperty(name='Retro: Japanese Font Scale', min=0, size=2)
|
|
frame_textpane_hjustifications = [
|
|
('LEFT', 'Left', '', 0),
|
|
('CENTER', 'Center', '', 1),
|
|
('RIGHT', 'Right', '', 2),
|
|
('FULL', 'Full', '', 3),
|
|
('NLEFT', 'Left Normalized', '', 4),
|
|
('NCENTER', 'Center Normalized', '', 5),
|
|
('NRIGHT', 'Right Normalized', '', 6),
|
|
('LEFTMONO', 'Left Monospaced', '', 7),
|
|
('CENTERMONO', 'Center Monospaced', '', 8),
|
|
('RIGHTMONO', 'Right Monospaced', '', 9)]
|
|
bpy.types.Object.retro_textpane_hjustification = bpy.props.EnumProperty(items=frame_textpane_hjustifications, name='Retro: Horizontal Justification', default='LEFT')
|
|
frame_textpane_vjustifications = [
|
|
('TOP', 'Top', '', 0),
|
|
('CENTER', 'Center', '', 1),
|
|
('BOTTOM', 'Bottom', '', 2),
|
|
('FULL', 'Full', '', 3),
|
|
('NTOP', 'Top Normalized', '', 4),
|
|
('NCENTER', 'Center Normalized', '', 5),
|
|
('NBOTTOM', 'Bottom Normalized', '', 6),
|
|
('TOPMONO', 'Top Monospaced', '', 7),
|
|
('CENTERMONO', 'Center Monospaced', '', 8),
|
|
('BOTTOMMONO', 'Bottom Monospaced', '', 9)]
|
|
bpy.types.Object.retro_textpane_vjustification = bpy.props.EnumProperty(items=frame_textpane_vjustifications, name='Retro: Vertical Justification', default='TOP')
|
|
|
|
bpy.types.Object.retro_tablegroup_elem_count = bpy.props.IntProperty(name='Retro: Table Group Element Count', min=0, default=0)
|
|
bpy.types.Object.retro_tablegroup_elem_default = bpy.props.IntProperty(name='Retro: Table Group Default Element', min=0, default=0)
|
|
bpy.types.Object.retro_tablegroup_wraparound = bpy.props.BoolProperty(name='Retro: Table Group Wraparound', default=False)
|
|
|
|
bpy.types.Object.retro_group_default_worker = bpy.props.IntProperty(name='Retro: Group Default Worker', min=0, default=0)
|
|
|
|
bpy.types.Object.retro_slider_min = bpy.props.FloatProperty(name='Retro: Slider Min', default=0.0)
|
|
bpy.types.Object.retro_slider_max = bpy.props.FloatProperty(name='Retro: Slider Max', default=1.0)
|
|
bpy.types.Object.retro_slider_default = bpy.props.FloatProperty(name='Retro: Slider Default', default=0.0)
|
|
bpy.types.Object.retro_slider_increment = bpy.props.FloatProperty(name='Retro: Slider Increment', min=0.0, default=1.0)
|
|
|
|
bpy.types.Object.retro_energybar_texture_path = bpy.props.StringProperty(name='Retro: Energy Bar Texture Path')
|
|
|
|
bpy.types.Object.retro_meter_no_round_up = bpy.props.BoolProperty(name='Retro: No Round Up', default=True)
|
|
bpy.types.Object.retro_meter_max_capacity = bpy.props.IntProperty(name='Retro: Max Capacity', min=0, default=100)
|
|
bpy.types.Object.retro_meter_worker_count = bpy.props.IntProperty(name='Retro: Worker Count', min=0, default=1)
|
|
|
|
bpy.types.Light.retro_light_index = bpy.props.IntProperty(name='Retro: Light Index', min=0, default=0)
|
|
bpy.types.Light.retro_light_angle_constant = bpy.props.FloatProperty(name='Retro: Light Angle Constant', min=0.0, default=0.0)
|
|
bpy.types.Light.retro_light_angle_linear = bpy.props.FloatProperty(name='Retro: Light Angle Linear', min=0.0, default=0.0)
|
|
bpy.types.Light.retro_light_angle_quadratic = bpy.props.FloatProperty(name='Retro: Light Angle Quadratic', min=0.0, default=0.0)
|
|
|