part of 'command_executor.dart'; extension _CommandExecutorTargetEffects on CommandExecutor { Future<_CommandResult> _movePath( RuntimeCommand command, _CommandContext context, RuntimeCommandHandle? handle, ) { final target = _requiredTarget(command); final component = _renderTree.componentById(target); if (component == null) { return Future.value(_CommandResult.cancelled); } final scope = _scopeFor(command, context, defaultTarget: true); final scopeEpoch = _scopeEpochFor(scope, context); final targetEpoch = _renderTree.epochOf(target); final task = _registerTask(scope, handle); final pathValue = command.payload['path'] as List; final duration = _duration(command, defaultValue: 0.4); final perStepDuration = duration / pathValue.length; final effects = []; for (final point in pathValue) { final map = point as Map; final x = _readDouble(map['x'])!; final y = _readDouble(map['y'])!; effects.add( MoveToEffect( Vector2(x, y), EffectController(duration: perStepDuration), ), ); } _appendCompletionEffect( effects, command, target, targetEpoch, task, scope, scopeEpoch, ); final effect = SequenceEffect(effects); handle?.addCancelCallback(effect.removeFromParent); component.add(effect); return task.future; } Future<_CommandResult> _targetEffect( RuntimeCommand command, _CommandContext context, RuntimeCommandHandle? handle, Effect Function(RuntimeComponent component, double duration) factory, ) { final target = _requiredTarget(command); final component = _renderTree.componentById(target); if (component == null) { return Future.value(_CommandResult.cancelled); } final scope = _scopeFor(command, context, defaultTarget: true); final scopeEpoch = _scopeEpochFor(scope, context); final targetEpoch = _renderTree.epochOf(target); final task = _registerTask(scope, handle); final effects = [ factory(component, _duration(command, defaultValue: 0.2)), ]; _appendCompletionEffect( effects, command, target, targetEpoch, task, scope, scopeEpoch, ); final effect = SequenceEffect(effects); handle?.addCancelCallback(effect.removeFromParent); component.add(effect); return task.future; } Future<_CommandResult> _playSpineAnimation( RuntimeCommand command, _CommandContext context, ) { final target = _requiredTarget(command); final component = _renderTree.componentById(target); if (component == null) { return Future.value(_CommandResult.cancelled); } final animation = _requiredSpineAnimation(command); final track = _optionalInt(command.payload['track'], 'play_spine_animation.track') ?? 0; final loop = _optionalBool(command.payload['loop'], 'play_spine_animation.loop') ?? true; final queue = _optionalBool(command.payload['queue'], 'play_spine_animation.queue') ?? false; final delay = _readDouble(command.payload['delay']) ?? 0; if (track < 0) { throw const FormatException('play_spine_animation.track must be >= 0'); } if (delay < 0) { throw const FormatException('play_spine_animation.delay must be >= 0'); } final played = component.playSpineAnimation( animation, track: track, loop: loop, queue: queue, delay: delay, ); if (!played) { return Future.value(_CommandResult.cancelled); } final scope = _completionScopeFor(command, context); _emitCompletion( command, target, scope, _renderTree.epochOf(target), context.scopeEpoch, ); return Future.value(_CommandResult.completed); } Future<_CommandResult> _removeNode( RuntimeCommand command, _CommandContext context, ) { final target = _requiredTarget(command); _renderTree.removeById(target); _emitCompletion(command, target, _completionScopeFor(command, context)); return Future.value(_CommandResult.completed); } }