Каждое изменение соответствует кадру. Изменение параметров объектов и сохранение кадров выполняется в цикле сценария Python.
Всё становится понятнее после осознания того, что любое действие, любое нажатие кнопкой мыши во FreeCAD лишь выполняет команду Python. Это можно увидеть открыв консоль Python (Вид - Панели - Консоль Python).
Пример кода
Код: Выделить всё
#!/usr/bin/env python
# -*- coding: utf-8 -*-
fps = 30 # Кадров в секунду
speed = 20 # Скорость, мм/сек
repeat = 1 # Количество повторов
pulley_length = 20 * 2 # Длина шкива, мм
angle_per_mm = 360/pulley_length # Градусов на 1 мм
x_max = 140 # Максимальный ход оси X
y_max = 140 # Максимальный ход оси Y
save_image = True # Сохранять кадры на каждом шаге
img_resolution_x = 3500
img_resolution_y = 2160
background = "White"
# ----------------------------------------------------------------------
from PySide import QtCore
from math import *
import datetime
if save_image:
doc_filename = FreeCAD.activeDocument().FileName
now = datetime.datetime.now()
filename = os.path.basename(doc_filename).partition('.')[0]
dirname = os.path.dirname(doc_filename) + "/" + filename + "_animation_" + now.strftime("%Y%m%d_%H%M")
os.mkdir(dirname)
image_count = 0
Gui.Selection.clearSelection()
Gui.Selection.addSelection('experiment','Part','LDE_Base_v4.')
Gui.Selection.addSelection('experiment','Part','LDE_Base_v4.E3D_Volcano_Hotend_v5.')
Gui.Selection.addSelection('experiment','Part','Part015.Part044.Pulley_20_Tooth_6mm.Part059049.')
Gui.Selection.addSelection('experiment','Part','Part015.Part044.Pulley_20_Tooth_6mm001.Part059050.')
element_1 = Gui.Selection.getSelection()[0]
x_start_1 = element_1.Placement.Base[0] # Координата X 1-го выделенного объекта
y_start_1 = element_1.Placement.Base[1] # Координата Y 1-го выделенного объекта
z_start_1 = element_1.Placement.Base[2] # Координата Z 1-го выделенного объекта
rotation_x_1 = element_1.Placement.Rotation.Axis.x
rotation_y_1 = element_1.Placement.Rotation.Axis.y
rotation_z_1 = element_1.Placement.Rotation.Axis.z
rotation_angle_1 = degrees(element_1.Placement.Rotation.Angle) # Угол поворота 1-го выделенного объекта
element_2 = Gui.Selection.getSelection()[1]
x_start_2 = element_2.Placement.Base[0] # Координата X 2-го выделенного объекта
y_start_2 = element_2.Placement.Base[1] # Координата Y 2-го выделенного объекта
z_start_2 = element_2.Placement.Base[2] # Координата Z 2-го выделенного объекта
rotation_x_2 = element_2.Placement.Rotation.Axis.x
rotation_y_2 = element_2.Placement.Rotation.Axis.y
rotation_z_2 = element_2.Placement.Rotation.Axis.z
rotation_angle_2 = degrees(element_2.Placement.Rotation.Angle) # Угол поворота 2-го выделенного объекта
element_3 = Gui.Selection.getSelection()[2]
x_start_3 = element_3.Placement.Base[0] # Координата X 1-го выделенного объекта
y_start_3 = element_3.Placement.Base[1] # Координата Y 1-го выделенного объекта
z_start_3 = element_3.Placement.Base[2] # Координата Z 1-го выделенного объекта
#rotation_x_3 = element_3.Placement.Rotation.Axis.x
rotation_x_3 = 0
#rotation_y_3 = element_3.Placement.Rotation.Axis.y
rotation_y_3 = 1
#rotation_z_3 = element_3.Placement.Rotation.Axis.z
rotation_z_3 = 0
rotation_angle_3 = degrees(element_3.Placement.Rotation.Angle) # Угол поворота 1-го выделенного объекта
element_4 = Gui.Selection.getSelection()[3]
x_start_4 = element_4.Placement.Base[0] # Координата X 1-го выделенного объекта
y_start_4 = element_4.Placement.Base[1] # Координата Y 1-го выделенного объекта
z_start_4 = element_4.Placement.Base[2] # Координата Z 1-го выделенного объекта
#rotation_x_4 = element_4.Placement.Rotation.Axis.x
rotation_x_4 = 0
#rotation_y_4 = element_4.Placement.Rotation.Axis.y
rotation_y_4 = 1
#rotation_z_4 = element_4.Placement.Rotation.Axis.z
rotation_z_4 = 0
rotation_angle_4 = degrees(element_4.Placement.Rotation.Angle) # Угол поворота 1-го выделенного объекта
text = FreeCAD.getDocument('experiment').getObject('Text')
Gui.Selection.clearSelection()
x_min = x_start_2 # Минимальная координата X
y_min = y_start_1 # Минимальная координата Y
step_move = speed / fps # Перемещение за один шаг, мм
x = x_start_2
y = y_start_1
step = 1
count = 0
angle3 = 0
angle4 = 0
def update():
global x
global y
global step
global count
global image_count
global angle3
global angle4
if x < x_min+x_max and step == 1:
x = x + step_move
angle3 = angle3 + step_move * angle_per_mm
angle4 = angle4 + step_move * angle_per_mm
elif step == 1:
step = 2
if x > x_min and step == 2:
x = x - step_move
angle3 = angle3 - step_move * angle_per_mm
angle4 = angle4 - step_move * angle_per_mm
elif step == 2:
x = x_min
y = y_min
step = 1
count += 1
element_1.Placement = App.Placement(App.Vector(x_start_1,y,z_start_1),App.Rotation(App.Vector(rotation_x_1,rotation_y_1,rotation_z_1),rotation_angle_1))
element_2.Placement = App.Placement(App.Vector(x,y_start_2,z_start_2),App.Rotation(App.Vector(rotation_x_2,rotation_y_2,rotation_z_2),rotation_angle_2))
element_3.Placement = App.Placement(App.Vector(x_start_3,y_start_3,z_start_3),App.Rotation(App.Vector(rotation_x_3,rotation_y_3,rotation_z_3),angle3))
element_4.Placement = App.Placement(App.Vector(x_start_4,y_start_4,z_start_4),App.Rotation(App.Vector(rotation_x_4,rotation_y_4,rotation_z_4),angle4))
text.Text = ["X" + str(round(150+x-x_min)) + " Y" + str(round(50+y-y_min)), ]
if save_image:
image_count += 1
Gui.activeDocument().activeView().saveImage(dirname + '/frame_' + str(image_count).zfill(5) + '.png',img_resolution_x,img_resolution_y,background)
if count == repeat: # Если все повторы выполнены,
timer.stop() # остановить таймер
timer = QtCore.QTimer()
timer.timeout.connect(update)
#timer.start(1/fps)
timer.start(100)