diff --git a/addon/__init__.py b/addon/__init__.py index 2dea484..4a3e0a3 100644 --- a/addon/__init__.py +++ b/addon/__init__.py @@ -6,6 +6,7 @@ from .ui.menu_panel import MenuPanel from .ops.json_export import JsonExport from .ops.arduino_export import ArduinoExport +from .ops.servoanim_export import ServoanimExport from .ops.stop_live_mode import StopLiveMode from .ops.install_dependencies import InstallDependencies from .ops.start_live_mode import StartLiveMode @@ -32,6 +33,7 @@ MenuPanel, ArduinoExport, JsonExport, + ServoanimExport, StopLiveMode, StartLiveMode, InstallDependencies, @@ -42,6 +44,7 @@ def menu_func_export(self, _): self.layout.operator(ArduinoExport.bl_idname) self.layout.operator(JsonExport.bl_idname) + self.layout.operator(ServoanimExport.bl_idname) def menu_func_timeline(self, _): diff --git a/addon/ops/servoanim_export.py b/addon/ops/servoanim_export.py new file mode 100644 index 0000000..6752545 --- /dev/null +++ b/addon/ops/servoanim_export.py @@ -0,0 +1,36 @@ +import bpy + +from bpy.types import Operator +from bpy_extras.io_utils import ExportHelper +from .base_export import BaseExport + + +class ServoanimExport(Operator, BaseExport, ExportHelper): + bl_idname = "export_anim.servo_positions_servoanim" + bl_label = "Animation Servo Positions (.servoanim)" + bl_description = "Save an SD card optimized file with servo position values of the active armature" + + filename_ext = ".servoanim" + + filter_glob: bpy.props.StringProperty( + default="*.servoanim", + options={'HIDDEN'}, + maxlen=255 + ) + + def export(self, positions, context): + fps, frames, seconds = self.get_time_meta(context.scene) + positions_keys = list(positions.keys()) + ids = ",".join(str(x) for x in positions_keys) + + content = f"fps:{fps} frames:{frames} seconds:{seconds} ids:{ids}\n\n" + + for frame in range(frames): + for servo_id in range(255): + if servo_id not in positions: + continue + pos = positions[servo_id][frame] + content += str(pos) + " " + content = content[:-1] + "\n" + + return content diff --git a/addon/ui/menu_panel.py b/addon/ui/menu_panel.py index 8129ab7..2b58ccd 100644 --- a/addon/ui/menu_panel.py +++ b/addon/ui/menu_panel.py @@ -1,6 +1,7 @@ from bpy.types import Panel from ..ops.json_export import JsonExport from ..ops.arduino_export import ArduinoExport +from ..ops.servoanim_export import ServoanimExport from ..ops.stop_live_mode import StopLiveMode from ..ops.install_dependencies import InstallDependencies from ..ops.start_live_mode import StartLiveMode @@ -31,6 +32,7 @@ def draw(self, context): 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)") @classmethod def draw_live_mode(cls, context, layout, col): diff --git a/examples/IK/ik.servoanim b/examples/IK/ik.servoanim new file mode 100644 index 0000000..c1ad172 --- /dev/null +++ b/examples/IK/ik.servoanim @@ -0,0 +1,102 @@ +fps:30 frames:100 seconds:3 ids:0,1 + +375 375 +376 376 +377 379 +380 383 +384 388 +387 394 +391 401 +396 409 +400 417 +403 426 +406 434 +408 443 +410 450 +410 457 +409 463 +406 468 +402 471 +396 472 +390 471 +382 469 +373 466 +364 462 +355 457 +346 452 +338 447 +330 441 +323 437 +318 432 +314 428 +311 424 +309 420 +307 416 +305 411 +305 407 +305 402 +305 398 +306 394 +307 389 +309 384 +311 380 +314 375 +317 370 +320 366 +323 361 +327 356 +331 352 +335 347 +339 342 +343 337 +347 333 +351 328 +356 324 +360 319 +364 315 +369 312 +374 309 +380 308 +386 307 +392 306 +398 306 +404 306 +410 307 +415 308 +420 309 +425 310 +429 311 +432 312 +435 313 +436 313 +437 313 +437 313 +436 314 +435 315 +434 316 +432 318 +430 320 +428 322 +426 324 +423 327 +421 329 +418 332 +415 335 +412 338 +409 341 +406 344 +403 347 +400 350 +397 353 +394 356 +391 359 +388 362 +386 364 +384 366 +381 369 +380 370 +378 372 +377 373 +376 374 +375 375 +375 375