Я забыл просмотреть текст, но, не важно, если ты знаешь о том, что bpm может быть записан двумя вариантами...
Вот мой черновик, может, что-то увидишь в нём полезное:
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
import os, subprocess
import bpy
from bpy.props import *
from bpy_extras.io_utils import ImportHelper
import xml.etree.ElementTree as ET
bl_info = {
"name": "Import LMMP Pattern to Scene (.mmp)",
"author": "blender-3d.ru/forum",
"version": (0, 0, 1),
"blender": (2, 78, 0),
"location": "File > Import > LMMP Pattern to Scene(.mmp)",
"description": "Imports LMMP files as a series of animation properties",
"category": "Import-Export",
}
"""
This script imports LMMP files into 3D Scenes (.mmp)
"""
def fingers_item_callback(self, context):
ob = context.object
items = [("1", "1", ""),
("2", "2", ""),
("3", "3", ""),
("4", "4", ""),
("5", "5", "")]
if ob.instrument_type == 'guitar':
items = [("b", "B", ""),
("1", "1", ""),
("2", "2", ""),
("3", "3", ""),
("4", "4", "")]
return items
class MusicPatternSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
bpy.types.TextCurve.music_pattern = PointerProperty(
name="Music Pattern Settings",
description="",
type=cls,
)
autocreate = BoolProperty()
midi_data_object = StringProperty()
musician_instrument = bpy.props.EnumProperty(
name="Musician or Instrument",
items=( ("instrument", "Instrument", ""),
("musician", "Musician", "")),
default="instrument")
instrument_type = bpy.props.EnumProperty(
name="Instrument Type",
items=( ("bowed", "Bowed Strings", ""),
("brass", "Brass Instruments", ""),
("guitar", "Guitar family", ""),
("keyboard", "Keyboard instruments", ""),
("percussion", "Percussion instruments", ""),
("woodwind", "Woodwind", "")),
default="keyboard")
@classmethod
def unregister(cls):
del bpy.types.TextCurve.music_pattern
class NoteSettingItem(bpy.types.PropertyGroup):
name = bpy.props.StringProperty()
index = bpy.props.IntProperty()
volume = bpy.props.IntProperty()
position = bpy.props.IntProperty()
duration = bpy.props.IntProperty()
hands = bpy.props.EnumProperty(
name="Hands",
items=( ("left", "Left", ""),
("right", "Right", ""),
("both", "Both", "")),
default="right")
left_hand = bpy.props.EnumProperty(
name="motion_left_hand",
items=( ("up", "Up", ""),
("down", "Down", ""),
("blow", "Blow", ""),
("fingers", "Fingers", "")),
default="blow")
fingers_left = bpy.props.EnumProperty(
name="Fingers Left Hand",
items=fingers_item_callback)
finger_connect_left = bpy.props.BoolProperty()
right_hand = bpy.props.EnumProperty(
name="motion_right_hand",
items=( ("up", "Up", ""),
("down", "Down", ""),
("blow", "Blow", ""),
("fingers", "Fingers", "")),
default="blow")
fingers_right = bpy.props.EnumProperty(
name="Fingers Right Hand",
items=fingers_item_callback)
finger_connect_right = bpy.props.BoolProperty()
class View3DPanel():
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
class VIEW3D_PT_lmms(View3DPanel, bpy.types.Panel):
bl_category = "Animation"
bl_context = "objectmode"
bl_label = "Musicians Animation with LMMS"
def draw(self, context):
ob=context.object
note = 0
if ob and ob.type == 'FONT' and len(ob.data.notes) > 0:
layout = self.layout
layout.prop_search(ob,"midi_data_object",context.blend_data,'objects',text='Musician')
layout.prop(ob,"auto")
ctx = ob.data.notes[note] #develop
layout.prop(ctx,"name")
layout.prop(ctx,"volume")
layout.prop(ctx,"position")
layout.prop(ctx,"duration")
layout.label('Hands:')
layout.prop(ctx,"hands",expand = True)
if ctx.hands in {'left','both'}:
layout.label('Left hand:')
layout.prop(ctx,"left_hand",expand = True)
if ctx.left_hand in {'fingers'}:
box = layout.box()
box.label('Fingers left hand')
box.prop(ctx,"fingers_left",text="1")
box.prop(ctx,"finger_connect_left",text="Leave Pressed")
if ctx.hands in {'right','both'}:
layout.label('Right hand:')
layout.prop(ctx,"right_hand",expand = True)
if ctx.right_hand in {'fingers'}:
box = layout.box()
box.label('Fingers right hand')
box.prop(ctx,"fingers_right",text="1")
box.prop(ctx,"finger_connect_right",text="Leave Pressed")
scale = 1
offset = 0
scene = None
startframe = 0
class LMMPPatternToScene(bpy.types.Operator, ImportHelper):
bl_idname = "import.lmmp_pattern_to_scene"
bl_label = "LMMP Pattern to Scene"
bl_description = "Imports notes from LMMP files into 3D Scenes"
bl_options = {'REGISTER', 'UNDO'}
filename_ext = {".mmp"}
filter_glob = StringProperty(
default="*.mmp",
options={'HIDDEN'},
)
Offset = FloatProperty(name="Offset Frame", description="Offset frame", min=0, default=1)
DefaultTicksPerTact = FloatProperty(name="Default Ticks Per Tact", description="Default ticks per tact", min=16, default=192)
def draw(self, context):
layout = self.layout
box = layout.box()
box.label('LMMP Pattern:', icon='SORTSIZE')
box.prop(self, 'Offset')
box.prop(self, 'DefaultTicksPerTact')
def execute(self, context):
scene = context.scene
fps = scene.render.fps
layers = 20*[False]
layers[0]=True
tree = ET.parse(self.filepath)
node = tree.getroot()
bpm = None
for head in node.findall('head'):
if 'bpm' in head.attrib:
bpm = int(head.attrib['bpm'])
if not bpm:
for child in head.findall('bpm'):
if 'value' in child.attrib:
bpm = int(child.attrib['value'])
scale = 60/bpm/(self.DefaultTicksPerTact/4)*fps
location = 0
for head in node.findall('song'):
for child_song in head.findall('trackcontainer'):
for child_trackcontainer in child_song.findall('track'):
for child_track in child_trackcontainer.findall('pattern'):
tname=child_track.attrib['name']
tpos=int(child_track.attrib['pos'])
tlen=int(child_track.attrib['len'])
bpy.ops.object.text_add(location=(0, 0, location), layers=layers)
ob = bpy.context.object
ob.data.body = tname
ob.name = tname
location += 0.1
for pnote in child_track.findall('note'):
note = ob.data.notes.add()
key=pnote.attrib['key']
pos=int(pnote.attrib['pos'])
len=int(pnote.attrib['len'])
vol=int(pnote.attrib['vol'])
note.name =
note.index =
note.volume =
note.position =
note.duration =
return {'FINISHED'}
def menu_func(self, context):
self.layout.operator(LMMPPatternToScene.bl_idname, text="LMMP Pattern to Scene (.mmp)", icon='PLUGIN')
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_file_import.append(menu_func)
bpy.types.TextCurve.notes = bpy.props.CollectionProperty(type=NoteSettingItem)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_file_import.remove(menu_func)
del bpy.types.TextCurve.notes
if __name__ == "__main__":
register()