From 39e316ba5eb6c3b5da711e1f7694b3006ae2330a Mon Sep 17 00:00:00 2001 From: Tim Hendriks Date: Wed, 24 Jan 2024 17:15:02 +0100 Subject: [PATCH] update JSON export structure --- .vscode/settings.json | 2 - addon/ops/arduino_export.py | 8 +- addon/ops/base_export.py | 22 +- addon/ops/json_export.py | 35 +- addon/ops/servoanim_export.py | 9 +- addon/ui/menu_panel.py | 11 +- addon/utils/converter.py | 67 +-- examples/IK/ik.json | 616 ++++++++++++++--------- examples/Scenes/scene-a.json | 423 +++++++++++----- examples/Scenes/scene-b.json | 809 +++++++++++++++++++++++-------- examples/Simple/simple.json | 423 +++++++++++----- tests/integration/test_export.py | 10 +- 12 files changed, 1689 insertions(+), 746 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index de05c10..47b698a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,4 @@ { - "python.linting.enabled": true, - "python.linting.pylintEnabled": true, "files.exclude": { "**/__pycache__": true }, diff --git a/addon/ops/arduino_export.py b/addon/ops/arduino_export.py index 2824c3b..b8e38d9 100644 --- a/addon/ops/arduino_export.py +++ b/addon/ops/arduino_export.py @@ -6,8 +6,8 @@ class ArduinoExport(Operator, BaseExport, ExportHelper): - bl_idname = "export_anim.servo_positions_arduino" - bl_label = "Animation Servo Positions (.h)" + bl_idname = "export_anim.servo_animation_arduino" + bl_label = "Servo Animation (.h)" bl_description = "Save an Arduino header file with servo position values of the active armature" filename_ext = ".h" @@ -49,11 +49,11 @@ def export(self, positions, filepath, context): content = ( "/*\n Blender Servo Animation Positions\n\n " f"FPS: {fps}\n Frames: {frames}\n Seconds: {seconds}\n " - f"Bones: {len(positions)}\n Armature: {context.object.name}\n " + f"Bones: {len(positions[0])}\n Armature: {context.object.name}\n " f"Scene: {context.scene.name}\n File: {filename}\n*/\n" ) - commands = self.get_commands(frames, positions) + commands = self.get_commands(positions) length = len(commands) lines = self.join_by_chunk_size(commands, self.chunk_size) progmem = 'PROGMEM ' if self.progmem else '' diff --git a/addon/ops/base_export.py b/addon/ops/base_export.py index a4d0db1..0e97f63 100644 --- a/addon/ops/base_export.py +++ b/addon/ops/base_export.py @@ -34,7 +34,7 @@ def execute(self, context): bpy.ops.servo_animation.stop_live_mode() try: - positions = calculate_positions(context) + positions = calculate_positions(context, self.skip_duplicates) self.export(positions, self.filepath, context) except RuntimeError as error: self.report({'ERROR'}, str(error)) @@ -53,25 +53,13 @@ def execute(self, context): return {'FINISHED'} - def get_commands(self, frames, positions): + def get_commands(self, positions): commands = [] - last_positions = {} - - for frame in range(frames): - for servo_id in range(255): - if servo_id not in positions: - continue - - if servo_id not in last_positions: - last_positions[servo_id] = None - - position = positions[servo_id][frame] - - if self.skip_duplicates and last_positions[servo_id] == position: - continue + for frame_positions in positions: + for servo_id in frame_positions: + position = frame_positions[servo_id] commands += self.get_command(servo_id, position) - last_positions[servo_id] = position commands.append(self.LINE_BREAK) diff --git a/addon/ops/json_export.py b/addon/ops/json_export.py index 6bde312..1990415 100644 --- a/addon/ops/json_export.py +++ b/addon/ops/json_export.py @@ -4,12 +4,11 @@ from bpy.types import Operator from bpy_extras.io_utils import ExportHelper from .base_export import BaseExport -from ..utils.servo_settings import get_pose_bone_by_servo_id class JsonExport(Operator, BaseExport, ExportHelper): - bl_idname = "export_anim.servo_positions_json" - bl_label = "Animation Servo Positions (.json)" + bl_idname = "export_anim.servo_animation_json" + bl_label = "Servo Animation (.json)" bl_description = "Save a JSON file with servo position values of the active armature" filename_ext = ".json" @@ -20,34 +19,40 @@ class JsonExport(Operator, BaseExport, ExportHelper): maxlen=255 ) - skip_duplicates: None + indent: bpy.props.EnumProperty( + name="Indent", + items=[ + ('None', 'No indent', ''), + ('1', '1 Space', ''), + ('2', '2 Spaces', ''), + ('3', '3 Spaces', ''), + ('4', '4 Spaces', ''), + ], + default='2', + ) def export(self, positions, filepath, context): fps, frames, seconds = self.get_time_meta(context.scene) filename = self.get_blend_filename() - servos = {} - - for servo_id in positions: - pose_bone = get_pose_bone_by_servo_id(servo_id, context.scene) - servos[servo_id] = { - "name": pose_bone.bone.name, - "positions": positions[servo_id], - } + try: + indent = int(self.indent) + except ValueError: + indent = None data = { "description": 'Blender Servo Animation Positions', "fps": fps, "frames": frames, "seconds": seconds, - "bones": len(positions), + "bones": len(positions[0]), "armature": context.object.name, "file": filename, "scene": context.scene.name, - "servos": servos + "positions": positions } - content = json.dumps(data, indent=4) + content = json.dumps(data, indent=indent) with open(filepath, 'w', encoding='utf-8') as file: file.write(content) diff --git a/addon/ops/servoanim_export.py b/addon/ops/servoanim_export.py index c58372a..a160049 100644 --- a/addon/ops/servoanim_export.py +++ b/addon/ops/servoanim_export.py @@ -6,8 +6,8 @@ class ServoanimExport(Operator, BaseExport, ExportHelper): - bl_idname = "export_anim.servo_positions_servoanim" - bl_label = "Animation Servo Positions (.servoanim)" + bl_idname = "export_anim.servo_animation_servoanim" + bl_label = "Servo Animation (.servoanim)" bl_description = "Save an SD card optimized file with servo position values of the active armature" filename_ext = ".servoanim" @@ -18,9 +18,8 @@ class ServoanimExport(Operator, BaseExport, ExportHelper): maxlen=255 ) - def export(self, positions, filepath, context): - _fps, frames, _seconds = self.get_time_meta(context.scene) - commands = self.get_commands(frames, positions) + def export(self, positions, filepath, _context): + commands = self.get_commands(positions) with open(filepath, 'wb') as file: file.write(bytes(commands)) diff --git a/addon/ui/menu_panel.py b/addon/ui/menu_panel.py index 2b58ccd..60d025a 100644 --- a/addon/ui/menu_panel.py +++ b/addon/ui/menu_panel.py @@ -9,7 +9,7 @@ class MenuPanel(Panel): - bl_label = "Servo Positions" + bl_label = "Servo Animation" bl_idname = "TIMELINE_PT_servo" bl_space_type = 'SEQUENCE_EDITOR' bl_region_type = 'HEADER' @@ -27,12 +27,11 @@ def draw(self, context): else: self.draw_live_mode_deps(col) - col = layout.column() + col = layout.column(align=True) col.label(text="Export") - row = col.row(align=True) - row.operator(ArduinoExport.bl_idname, text="Arduino (.h)") - row.operator(JsonExport.bl_idname, text="JSON (.json)") - row.operator(ServoanimExport.bl_idname, text="Servoanim (.servoanim)") + col.operator(ArduinoExport.bl_idname, text="Arduino (.h)") + col.operator(JsonExport.bl_idname, text="JSON (.json)") + col.operator(ServoanimExport.bl_idname, text="Servoanim (.servoanim)") @classmethod def draw_live_mode(cls, context, layout, col): diff --git a/addon/utils/converter.py b/addon/utils/converter.py index 97a284f..ffde9a7 100644 --- a/addon/utils/converter.py +++ b/addon/utils/converter.py @@ -42,53 +42,62 @@ def calculate_position(pose_bone): angle = servo_settings.neutral_angle - rotation_in_degrees position = round(range_map(angle, 0, servo_settings.rotation_range, - servo_settings.position_min, servo_settings.position_max)) + servo_settings.position_min, servo_settings.position_max)) - check_min = servo_settings.position_min - check_max = servo_settings.position_max - - if position < check_min or position > check_max: - in_range = False - else: - in_range = True + in_range = servo_settings.position_min <= position <= servo_settings.position_max return position, round(angle, 2), in_range -def calculate_positions(context): +def calculate_positions(context, skip_duplicates): pose_bones = [] - scene = context.scene + positions = [] + last_positions = {} window_manager = context.window_manager - start = scene.frame_start - end = scene.frame_end + 1 + start = context.scene.frame_start + end = context.scene.frame_end + 1 - positions = {} + window_manager.progress_begin(min=start, max=end) for pose_bone in context.object.pose.bones: servo_settings = pose_bone.bone.servo_settings if servo_settings.active: pose_bones.append(pose_bone) - positions[servo_settings.servo_id] = [] - - window_manager.progress_begin(min=start, max=end) for frame in range(start, end): - scene.frame_set(frame) + frame_positions = calculate_frame_positions( + context, pose_bones, last_positions, skip_duplicates, frame) + positions.append(frame_positions) + window_manager.progress_update(frame) + + window_manager.progress_end() - for pose_bone in pose_bones: - bone = pose_bone.bone - position, _angle, in_range = calculate_position(pose_bone) + return positions - if not in_range: - raise RuntimeError( - f"Calculated position {position} for bone {bone.name} " - + f"is out of range at frame {frame}." - ) - positions[bone.servo_settings.servo_id].append(position) +def calculate_frame_positions(context, pose_bones, last_positions, skip_duplicates, frame): + frame_positions = {} - window_manager.progress_update(frame) + context.scene.frame_set(frame) - window_manager.progress_end() + for pose_bone in pose_bones: + bone = pose_bone.bone + servo_id = bone.servo_settings.servo_id + position, _angle, in_range = calculate_position(pose_bone) - return positions + if servo_id not in last_positions: + last_positions[servo_id] = None + + if not in_range: + raise RuntimeError( + f"Calculated position {position} for bone {bone.name} " + + f"is out of range at frame {frame}." + ) + + if skip_duplicates and last_positions[servo_id] == position: + continue + + frame_positions[servo_id] = position + last_positions[servo_id] = position + + return frame_positions diff --git a/examples/IK/ik.json b/examples/IK/ik.json index c556d03..f052463 100644 --- a/examples/IK/ik.json +++ b/examples/IK/ik.json @@ -1,222 +1,398 @@ { - "description": "Blender Servo Animation Positions", - "fps": 30, - "frames": 100, - "seconds": 3, - "bones": 2, - "armature": "Armature", - "file": "ik.blend", - "scene": "Scene", - "servos": { - "0": { - "name": "Neck Left", - "positions": [ - 375, - 376, - 377, - 380, - 384, - 387, - 391, - 396, - 400, - 403, - 406, - 408, - 410, - 410, - 409, - 406, - 402, - 396, - 390, - 382, - 373, - 364, - 355, - 346, - 338, - 330, - 323, - 318, - 314, - 311, - 309, - 307, - 305, - 305, - 305, - 305, - 306, - 307, - 309, - 311, - 314, - 317, - 320, - 323, - 327, - 331, - 335, - 339, - 343, - 347, - 351, - 356, - 360, - 364, - 369, - 374, - 380, - 386, - 392, - 398, - 404, - 410, - 415, - 420, - 425, - 429, - 432, - 435, - 436, - 437, - 437, - 436, - 435, - 434, - 432, - 430, - 428, - 426, - 423, - 421, - 418, - 415, - 412, - 409, - 406, - 403, - 400, - 397, - 394, - 391, - 388, - 386, - 384, - 381, - 380, - 378, - 377, - 376, - 375, - 375 - ] - }, - "1": { - "name": "Neck Right", - "positions": [ - 375, - 376, - 379, - 383, - 388, - 394, - 401, - 409, - 417, - 426, - 434, - 443, - 450, - 457, - 463, - 468, - 471, - 472, - 471, - 469, - 466, - 462, - 457, - 452, - 447, - 441, - 437, - 432, - 428, - 424, - 420, - 416, - 411, - 407, - 402, - 398, - 394, - 389, - 384, - 380, - 375, - 370, - 366, - 361, - 356, - 352, - 347, - 342, - 337, - 333, - 328, - 324, - 319, - 315, - 312, - 309, - 308, - 307, - 306, - 306, - 306, - 307, - 308, - 309, - 310, - 311, - 312, - 313, - 313, - 313, - 313, - 314, - 315, - 316, - 318, - 320, - 322, - 324, - 327, - 329, - 332, - 335, - 338, - 341, - 344, - 347, - 350, - 353, - 356, - 359, - 362, - 364, - 366, - 369, - 370, - 372, - 373, - 374, - 375, - 375 - ] - } - } + "description": "Blender Servo Animation Positions", + "fps": 30, + "frames": 100, + "seconds": 3, + "bones": 2, + "armature": "Armature", + "file": "ik.blend", + "scene": "Scene", + "positions": [ + { + "0": 375, + "1": 375 + }, + { + "0": 376, + "1": 376 + }, + { + "0": 377, + "1": 379 + }, + { + "0": 380, + "1": 383 + }, + { + "0": 384, + "1": 388 + }, + { + "0": 387, + "1": 394 + }, + { + "0": 391, + "1": 401 + }, + { + "0": 396, + "1": 409 + }, + { + "0": 400, + "1": 417 + }, + { + "0": 403, + "1": 426 + }, + { + "0": 406, + "1": 434 + }, + { + "0": 408, + "1": 443 + }, + { + "0": 410, + "1": 450 + }, + { + "1": 457 + }, + { + "0": 409, + "1": 463 + }, + { + "0": 406, + "1": 468 + }, + { + "0": 402, + "1": 471 + }, + { + "0": 396, + "1": 472 + }, + { + "0": 390, + "1": 471 + }, + { + "0": 382, + "1": 469 + }, + { + "0": 373, + "1": 466 + }, + { + "0": 364, + "1": 462 + }, + { + "0": 355, + "1": 457 + }, + { + "0": 346, + "1": 452 + }, + { + "0": 338, + "1": 447 + }, + { + "0": 330, + "1": 441 + }, + { + "0": 323, + "1": 437 + }, + { + "0": 318, + "1": 432 + }, + { + "0": 314, + "1": 428 + }, + { + "0": 311, + "1": 424 + }, + { + "0": 309, + "1": 420 + }, + { + "0": 307, + "1": 416 + }, + { + "0": 305, + "1": 411 + }, + { + "1": 407 + }, + { + "1": 402 + }, + { + "1": 398 + }, + { + "0": 306, + "1": 394 + }, + { + "0": 307, + "1": 389 + }, + { + "0": 309, + "1": 384 + }, + { + "0": 311, + "1": 380 + }, + { + "0": 314, + "1": 375 + }, + { + "0": 317, + "1": 370 + }, + { + "0": 320, + "1": 366 + }, + { + "0": 323, + "1": 361 + }, + { + "0": 327, + "1": 356 + }, + { + "0": 331, + "1": 352 + }, + { + "0": 335, + "1": 347 + }, + { + "0": 339, + "1": 342 + }, + { + "0": 343, + "1": 337 + }, + { + "0": 347, + "1": 333 + }, + { + "0": 351, + "1": 328 + }, + { + "0": 356, + "1": 324 + }, + { + "0": 360, + "1": 319 + }, + { + "0": 364, + "1": 315 + }, + { + "0": 369, + "1": 312 + }, + { + "0": 374, + "1": 309 + }, + { + "0": 380, + "1": 308 + }, + { + "0": 386, + "1": 307 + }, + { + "0": 392, + "1": 306 + }, + { + "0": 398 + }, + { + "0": 404 + }, + { + "0": 410, + "1": 307 + }, + { + "0": 415, + "1": 308 + }, + { + "0": 420, + "1": 309 + }, + { + "0": 425, + "1": 310 + }, + { + "0": 429, + "1": 311 + }, + { + "0": 432, + "1": 312 + }, + { + "0": 435, + "1": 313 + }, + { + "0": 436 + }, + { + "0": 437 + }, + {}, + { + "0": 436, + "1": 314 + }, + { + "0": 435, + "1": 315 + }, + { + "0": 434, + "1": 316 + }, + { + "0": 432, + "1": 318 + }, + { + "0": 430, + "1": 320 + }, + { + "0": 428, + "1": 322 + }, + { + "0": 426, + "1": 324 + }, + { + "0": 423, + "1": 327 + }, + { + "0": 421, + "1": 329 + }, + { + "0": 418, + "1": 332 + }, + { + "0": 415, + "1": 335 + }, + { + "0": 412, + "1": 338 + }, + { + "0": 409, + "1": 341 + }, + { + "0": 406, + "1": 344 + }, + { + "0": 403, + "1": 347 + }, + { + "0": 400, + "1": 350 + }, + { + "0": 397, + "1": 353 + }, + { + "0": 394, + "1": 356 + }, + { + "0": 391, + "1": 359 + }, + { + "0": 388, + "1": 362 + }, + { + "0": 386, + "1": 364 + }, + { + "0": 384, + "1": 366 + }, + { + "0": 381, + "1": 369 + }, + { + "0": 380, + "1": 370 + }, + { + "0": 378, + "1": 372 + }, + { + "0": 377, + "1": 373 + }, + { + "0": 376, + "1": 374 + }, + { + "0": 375, + "1": 375 + }, + {} + ] } \ No newline at end of file diff --git a/examples/Scenes/scene-a.json b/examples/Scenes/scene-a.json index b2038b1..50c7ef1 100644 --- a/examples/Scenes/scene-a.json +++ b/examples/Scenes/scene-a.json @@ -1,117 +1,312 @@ { - "description": "Blender Servo Animation Positions", - "fps": 30, - "frames": 100, - "seconds": 3, - "bones": 1, - "armature": "Armature", - "file": "scenes.blend", - "scene": "SceneA", - "servos": { - "0": { - "name": "Bone", - "positions": [ - 1472, - 1473, - 1477, - 1483, - 1492, - 1502, - 1515, - 1529, - 1544, - 1562, - 1580, - 1599, - 1619, - 1640, - 1661, - 1682, - 1704, - 1726, - 1747, - 1768, - 1789, - 1809, - 1828, - 1846, - 1864, - 1879, - 1893, - 1906, - 1916, - 1925, - 1931, - 1935, - 1936, - 1934, - 1926, - 1914, - 1898, - 1879, - 1855, - 1828, - 1799, - 1767, - 1732, - 1695, - 1657, - 1617, - 1577, - 1535, - 1493, - 1451, - 1409, - 1367, - 1327, - 1287, - 1249, - 1212, - 1177, - 1145, - 1116, - 1089, - 1065, - 1046, - 1030, - 1018, - 1010, - 1008, - 1009, - 1013, - 1018, - 1026, - 1035, - 1046, - 1059, - 1073, - 1088, - 1105, - 1122, - 1141, - 1160, - 1179, - 1199, - 1220, - 1240, - 1260, - 1281, - 1301, - 1320, - 1339, - 1358, - 1375, - 1392, - 1407, - 1421, - 1434, - 1445, - 1454, - 1462, - 1467, - 1471, - 1472 - ] - } + "description": "Blender Servo Animation Positions", + "fps": 30, + "frames": 100, + "seconds": 3, + "bones": 1, + "armature": "Armature", + "file": "scenes.blend", + "scene": "SceneA", + "positions": [ + { + "0": 1472 + }, + { + "0": 1473 + }, + { + "0": 1477 + }, + { + "0": 1483 + }, + { + "0": 1492 + }, + { + "0": 1502 + }, + { + "0": 1515 + }, + { + "0": 1529 + }, + { + "0": 1544 + }, + { + "0": 1562 + }, + { + "0": 1580 + }, + { + "0": 1599 + }, + { + "0": 1619 + }, + { + "0": 1640 + }, + { + "0": 1661 + }, + { + "0": 1682 + }, + { + "0": 1704 + }, + { + "0": 1726 + }, + { + "0": 1747 + }, + { + "0": 1768 + }, + { + "0": 1789 + }, + { + "0": 1809 + }, + { + "0": 1828 + }, + { + "0": 1846 + }, + { + "0": 1864 + }, + { + "0": 1879 + }, + { + "0": 1893 + }, + { + "0": 1906 + }, + { + "0": 1916 + }, + { + "0": 1925 + }, + { + "0": 1931 + }, + { + "0": 1935 + }, + { + "0": 1936 + }, + { + "0": 1934 + }, + { + "0": 1926 + }, + { + "0": 1914 + }, + { + "0": 1898 + }, + { + "0": 1879 + }, + { + "0": 1855 + }, + { + "0": 1828 + }, + { + "0": 1799 + }, + { + "0": 1767 + }, + { + "0": 1732 + }, + { + "0": 1695 + }, + { + "0": 1657 + }, + { + "0": 1617 + }, + { + "0": 1577 + }, + { + "0": 1535 + }, + { + "0": 1493 + }, + { + "0": 1451 + }, + { + "0": 1409 + }, + { + "0": 1367 + }, + { + "0": 1327 + }, + { + "0": 1287 + }, + { + "0": 1249 + }, + { + "0": 1212 + }, + { + "0": 1177 + }, + { + "0": 1145 + }, + { + "0": 1116 + }, + { + "0": 1089 + }, + { + "0": 1065 + }, + { + "0": 1046 + }, + { + "0": 1030 + }, + { + "0": 1018 + }, + { + "0": 1010 + }, + { + "0": 1008 + }, + { + "0": 1009 + }, + { + "0": 1013 + }, + { + "0": 1018 + }, + { + "0": 1026 + }, + { + "0": 1035 + }, + { + "0": 1046 + }, + { + "0": 1059 + }, + { + "0": 1073 + }, + { + "0": 1088 + }, + { + "0": 1105 + }, + { + "0": 1122 + }, + { + "0": 1141 + }, + { + "0": 1160 + }, + { + "0": 1179 + }, + { + "0": 1199 + }, + { + "0": 1220 + }, + { + "0": 1240 + }, + { + "0": 1260 + }, + { + "0": 1281 + }, + { + "0": 1301 + }, + { + "0": 1320 + }, + { + "0": 1339 + }, + { + "0": 1358 + }, + { + "0": 1375 + }, + { + "0": 1392 + }, + { + "0": 1407 + }, + { + "0": 1421 + }, + { + "0": 1434 + }, + { + "0": 1445 + }, + { + "0": 1454 + }, + { + "0": 1462 + }, + { + "0": 1467 + }, + { + "0": 1471 + }, + { + "0": 1472 } + ] } \ No newline at end of file diff --git a/examples/Scenes/scene-b.json b/examples/Scenes/scene-b.json index e191655..e1d72b9 100644 --- a/examples/Scenes/scene-b.json +++ b/examples/Scenes/scene-b.json @@ -1,217 +1,596 @@ { - "description": "Blender Servo Animation Positions", - "fps": 60, - "frames": 200, - "seconds": 3, - "bones": 1, - "armature": "Armature.001", - "file": "scenes.blend", - "scene": "SceneB", - "servos": { - "0": { - "name": "Bone", - "positions": [ - 1472, - 1472, - 1473, - 1473, - 1474, - 1475, - 1477, - 1479, - 1481, - 1483, - 1485, - 1488, - 1491, - 1494, - 1497, - 1501, - 1504, - 1508, - 1512, - 1517, - 1521, - 1526, - 1531, - 1536, - 1541, - 1546, - 1551, - 1557, - 1562, - 1568, - 1574, - 1580, - 1586, - 1592, - 1599, - 1605, - 1611, - 1618, - 1625, - 1631, - 1638, - 1645, - 1652, - 1659, - 1666, - 1672, - 1679, - 1686, - 1693, - 1700, - 1708, - 1715, - 1722, - 1729, - 1736, - 1742, - 1749, - 1756, - 1763, - 1770, - 1777, - 1783, - 1790, - 1797, - 1803, - 1809, - 1816, - 1822, - 1828, - 1834, - 1840, - 1846, - 1851, - 1857, - 1862, - 1867, - 1872, - 1877, - 1882, - 1887, - 1891, - 1896, - 1900, - 1904, - 1907, - 1911, - 1914, - 1917, - 1920, - 1923, - 1925, - 1927, - 1929, - 1931, - 1933, - 1934, - 1935, - 1935, - 1936, - 1936, - 1936, - 1935, - 1935, - 1934, - 1933, - 1931, - 1930, - 1928, - 1925, - 1923, - 1920, - 1918, - 1915, - 1911, - 1908, - 1904, - 1900, - 1896, - 1892, - 1888, - 1883, - 1878, - 1874, - 1869, - 1864, - 1858, - 1853, - 1847, - 1842, - 1836, - 1830, - 1824, - 1818, - 1812, - 1805, - 1799, - 1792, - 1786, - 1779, - 1773, - 1766, - 1759, - 1752, - 1746, - 1739, - 1732, - 1725, - 1718, - 1711, - 1704, - 1697, - 1690, - 1683, - 1676, - 1669, - 1662, - 1656, - 1649, - 1642, - 1635, - 1629, - 1622, - 1616, - 1609, - 1603, - 1596, - 1590, - 1584, - 1578, - 1572, - 1566, - 1561, - 1555, - 1550, - 1544, - 1539, - 1534, - 1530, - 1525, - 1520, - 1516, - 1512, - 1508, - 1504, - 1500, - 1497, - 1493, - 1490, - 1488, - 1485, - 1483, - 1480, - 1478, - 1477, - 1475, - 1474, - 1473, - 1473, - 1472, - 1472 - ] - } - } + "description": "Blender Servo Animation Positions", + "fps": 60, + "frames": 200, + "seconds": 3, + "bones": 0, + "armature": "Armature.001", + "file": "scenes.blend", + "scene": "SceneB", + "positions": [ + { + "0": 1472 + }, + {}, + { + "0": 1473 + }, + {}, + { + "0": 1474 + }, + { + "0": 1475 + }, + { + "0": 1477 + }, + { + "0": 1479 + }, + { + "0": 1481 + }, + { + "0": 1483 + }, + { + "0": 1485 + }, + { + "0": 1488 + }, + { + "0": 1491 + }, + { + "0": 1494 + }, + { + "0": 1497 + }, + { + "0": 1501 + }, + { + "0": 1504 + }, + { + "0": 1508 + }, + { + "0": 1512 + }, + { + "0": 1517 + }, + { + "0": 1521 + }, + { + "0": 1526 + }, + { + "0": 1531 + }, + { + "0": 1536 + }, + { + "0": 1541 + }, + { + "0": 1546 + }, + { + "0": 1551 + }, + { + "0": 1557 + }, + { + "0": 1562 + }, + { + "0": 1568 + }, + { + "0": 1574 + }, + { + "0": 1580 + }, + { + "0": 1586 + }, + { + "0": 1592 + }, + { + "0": 1599 + }, + { + "0": 1605 + }, + { + "0": 1611 + }, + { + "0": 1618 + }, + { + "0": 1625 + }, + { + "0": 1631 + }, + { + "0": 1638 + }, + { + "0": 1645 + }, + { + "0": 1652 + }, + { + "0": 1659 + }, + { + "0": 1666 + }, + { + "0": 1672 + }, + { + "0": 1679 + }, + { + "0": 1686 + }, + { + "0": 1693 + }, + { + "0": 1700 + }, + { + "0": 1708 + }, + { + "0": 1715 + }, + { + "0": 1722 + }, + { + "0": 1729 + }, + { + "0": 1736 + }, + { + "0": 1742 + }, + { + "0": 1749 + }, + { + "0": 1756 + }, + { + "0": 1763 + }, + { + "0": 1770 + }, + { + "0": 1777 + }, + { + "0": 1783 + }, + { + "0": 1790 + }, + { + "0": 1797 + }, + { + "0": 1803 + }, + { + "0": 1809 + }, + { + "0": 1816 + }, + { + "0": 1822 + }, + { + "0": 1828 + }, + { + "0": 1834 + }, + { + "0": 1840 + }, + { + "0": 1846 + }, + { + "0": 1851 + }, + { + "0": 1857 + }, + { + "0": 1862 + }, + { + "0": 1867 + }, + { + "0": 1872 + }, + { + "0": 1877 + }, + { + "0": 1882 + }, + { + "0": 1887 + }, + { + "0": 1891 + }, + { + "0": 1896 + }, + { + "0": 1900 + }, + { + "0": 1904 + }, + { + "0": 1907 + }, + { + "0": 1911 + }, + { + "0": 1914 + }, + { + "0": 1917 + }, + { + "0": 1920 + }, + { + "0": 1923 + }, + { + "0": 1925 + }, + { + "0": 1927 + }, + { + "0": 1929 + }, + { + "0": 1931 + }, + { + "0": 1933 + }, + { + "0": 1934 + }, + { + "0": 1935 + }, + {}, + { + "0": 1936 + }, + {}, + {}, + { + "0": 1935 + }, + {}, + { + "0": 1934 + }, + { + "0": 1933 + }, + { + "0": 1931 + }, + { + "0": 1930 + }, + { + "0": 1928 + }, + { + "0": 1925 + }, + { + "0": 1923 + }, + { + "0": 1920 + }, + { + "0": 1918 + }, + { + "0": 1915 + }, + { + "0": 1911 + }, + { + "0": 1908 + }, + { + "0": 1904 + }, + { + "0": 1900 + }, + { + "0": 1896 + }, + { + "0": 1892 + }, + { + "0": 1888 + }, + { + "0": 1883 + }, + { + "0": 1878 + }, + { + "0": 1874 + }, + { + "0": 1869 + }, + { + "0": 1864 + }, + { + "0": 1858 + }, + { + "0": 1853 + }, + { + "0": 1847 + }, + { + "0": 1842 + }, + { + "0": 1836 + }, + { + "0": 1830 + }, + { + "0": 1824 + }, + { + "0": 1818 + }, + { + "0": 1812 + }, + { + "0": 1805 + }, + { + "0": 1799 + }, + { + "0": 1792 + }, + { + "0": 1786 + }, + { + "0": 1779 + }, + { + "0": 1773 + }, + { + "0": 1766 + }, + { + "0": 1759 + }, + { + "0": 1752 + }, + { + "0": 1746 + }, + { + "0": 1739 + }, + { + "0": 1732 + }, + { + "0": 1725 + }, + { + "0": 1718 + }, + { + "0": 1711 + }, + { + "0": 1704 + }, + { + "0": 1697 + }, + { + "0": 1690 + }, + { + "0": 1683 + }, + { + "0": 1676 + }, + { + "0": 1669 + }, + { + "0": 1662 + }, + { + "0": 1656 + }, + { + "0": 1649 + }, + { + "0": 1642 + }, + { + "0": 1635 + }, + { + "0": 1629 + }, + { + "0": 1622 + }, + { + "0": 1616 + }, + { + "0": 1609 + }, + { + "0": 1603 + }, + { + "0": 1596 + }, + { + "0": 1590 + }, + { + "0": 1584 + }, + { + "0": 1578 + }, + { + "0": 1572 + }, + { + "0": 1566 + }, + { + "0": 1561 + }, + { + "0": 1555 + }, + { + "0": 1550 + }, + { + "0": 1544 + }, + { + "0": 1539 + }, + { + "0": 1534 + }, + { + "0": 1530 + }, + { + "0": 1525 + }, + { + "0": 1520 + }, + { + "0": 1516 + }, + { + "0": 1512 + }, + { + "0": 1508 + }, + { + "0": 1504 + }, + { + "0": 1500 + }, + { + "0": 1497 + }, + { + "0": 1493 + }, + { + "0": 1490 + }, + { + "0": 1488 + }, + { + "0": 1485 + }, + { + "0": 1483 + }, + { + "0": 1480 + }, + { + "0": 1478 + }, + { + "0": 1477 + }, + { + "0": 1475 + }, + { + "0": 1474 + }, + { + "0": 1473 + }, + {}, + { + "0": 1472 + }, + {} + ] } \ No newline at end of file diff --git a/examples/Simple/simple.json b/examples/Simple/simple.json index f33bfd5..88c8808 100644 --- a/examples/Simple/simple.json +++ b/examples/Simple/simple.json @@ -1,117 +1,312 @@ { - "description": "Blender Servo Animation Positions", - "fps": 30, - "frames": 100, - "seconds": 3, - "bones": 1, - "armature": "Armature", - "file": "simple.blend", - "scene": "Scene", - "servos": { - "0": { - "name": "Bone", - "positions": [ - 1472, - 1475, - 1482, - 1495, - 1512, - 1533, - 1558, - 1586, - 1617, - 1651, - 1687, - 1726, - 1766, - 1807, - 1849, - 1893, - 1936, - 1979, - 2023, - 2065, - 2106, - 2146, - 2185, - 2221, - 2255, - 2286, - 2314, - 2339, - 2360, - 2377, - 2390, - 2397, - 2400, - 2395, - 2380, - 2357, - 2325, - 2285, - 2238, - 2185, - 2126, - 2061, - 1992, - 1919, - 1842, - 1763, - 1681, - 1598, - 1514, - 1430, - 1346, - 1263, - 1181, - 1102, - 1025, - 952, - 883, - 818, - 759, - 706, - 659, - 619, - 587, - 564, - 549, - 544, - 546, - 553, - 564, - 579, - 598, - 621, - 646, - 674, - 705, - 738, - 773, - 809, - 847, - 886, - 927, - 967, - 1008, - 1049, - 1089, - 1130, - 1169, - 1207, - 1243, - 1278, - 1311, - 1342, - 1370, - 1395, - 1418, - 1437, - 1452, - 1463, - 1470, - 1472 - ] - } + "description": "Blender Servo Animation Positions", + "fps": 30, + "frames": 100, + "seconds": 3, + "bones": 1, + "armature": "Armature", + "file": "simple.blend", + "scene": "Scene", + "positions": [ + { + "0": 1472 + }, + { + "0": 1475 + }, + { + "0": 1482 + }, + { + "0": 1495 + }, + { + "0": 1512 + }, + { + "0": 1533 + }, + { + "0": 1558 + }, + { + "0": 1586 + }, + { + "0": 1617 + }, + { + "0": 1651 + }, + { + "0": 1687 + }, + { + "0": 1726 + }, + { + "0": 1766 + }, + { + "0": 1807 + }, + { + "0": 1849 + }, + { + "0": 1893 + }, + { + "0": 1936 + }, + { + "0": 1979 + }, + { + "0": 2023 + }, + { + "0": 2065 + }, + { + "0": 2106 + }, + { + "0": 2146 + }, + { + "0": 2185 + }, + { + "0": 2221 + }, + { + "0": 2255 + }, + { + "0": 2286 + }, + { + "0": 2314 + }, + { + "0": 2339 + }, + { + "0": 2360 + }, + { + "0": 2377 + }, + { + "0": 2390 + }, + { + "0": 2397 + }, + { + "0": 2400 + }, + { + "0": 2395 + }, + { + "0": 2380 + }, + { + "0": 2357 + }, + { + "0": 2325 + }, + { + "0": 2285 + }, + { + "0": 2238 + }, + { + "0": 2185 + }, + { + "0": 2126 + }, + { + "0": 2061 + }, + { + "0": 1992 + }, + { + "0": 1919 + }, + { + "0": 1842 + }, + { + "0": 1763 + }, + { + "0": 1681 + }, + { + "0": 1598 + }, + { + "0": 1514 + }, + { + "0": 1430 + }, + { + "0": 1346 + }, + { + "0": 1263 + }, + { + "0": 1181 + }, + { + "0": 1102 + }, + { + "0": 1025 + }, + { + "0": 952 + }, + { + "0": 883 + }, + { + "0": 818 + }, + { + "0": 759 + }, + { + "0": 706 + }, + { + "0": 659 + }, + { + "0": 619 + }, + { + "0": 587 + }, + { + "0": 564 + }, + { + "0": 549 + }, + { + "0": 544 + }, + { + "0": 546 + }, + { + "0": 553 + }, + { + "0": 564 + }, + { + "0": 579 + }, + { + "0": 598 + }, + { + "0": 621 + }, + { + "0": 646 + }, + { + "0": 674 + }, + { + "0": 705 + }, + { + "0": 738 + }, + { + "0": 773 + }, + { + "0": 809 + }, + { + "0": 847 + }, + { + "0": 886 + }, + { + "0": 927 + }, + { + "0": 967 + }, + { + "0": 1008 + }, + { + "0": 1049 + }, + { + "0": 1089 + }, + { + "0": 1130 + }, + { + "0": 1169 + }, + { + "0": 1207 + }, + { + "0": 1243 + }, + { + "0": 1278 + }, + { + "0": 1311 + }, + { + "0": 1342 + }, + { + "0": 1370 + }, + { + "0": 1395 + }, + { + "0": 1418 + }, + { + "0": 1437 + }, + { + "0": 1452 + }, + { + "0": 1463 + }, + { + "0": 1470 + }, + { + "0": 1472 } + ] } \ No newline at end of file diff --git a/tests/integration/test_export.py b/tests/integration/test_export.py index 8036933..47f0440 100644 --- a/tests/integration/test_export.py +++ b/tests/integration/test_export.py @@ -49,7 +49,7 @@ def test_json_export(self, _name, precision, expected): if os.path.exists(export_file): os.remove(export_file) - bpy.ops.export_anim.servo_positions_json(filepath=export_file, precision=precision) + bpy.ops.export_anim.servo_animation_json(filepath=export_file, precision=precision) assert os.path.exists(export_file), "expected export file to be present" @@ -78,7 +78,7 @@ def test_arduino_export(self, _name, precision, expected, namespace): if os.path.exists(export_file): os.remove(export_file) - bpy.ops.export_anim.servo_positions_arduino( + bpy.ops.export_anim.servo_animation_arduino( filepath=export_file, precision=precision, namespace=namespace @@ -125,16 +125,16 @@ def test_no_servo_settings(self, export_type, extension): try: if export_type == "arduino": - bpy.ops.export_anim.servo_positions_arduino(filepath=export_file) + bpy.ops.export_anim.servo_animation_arduino(filepath=export_file) elif export_type == "json": - bpy.ops.export_anim.servo_positions_json(filepath=export_file) + bpy.ops.export_anim.servo_animation_json(filepath=export_file) except RuntimeError as error: error_msg = str(error) assert not os.path.exists(export_file), "did not expect export file to be present" exp = ( - f"Operator bpy.ops.export_anim.servo_positions_{export_type}.poll() failed, " + f"Operator bpy.ops.export_anim.servo_animation_{export_type}.poll() failed, " "context is incorrect" ) got = error_msg