Pivy
Pivy это python библаотека привязанная к Coin3d, библиотеке 3D-рендеринга используемой FreeCAD-ом. Когда он импортирован, в запущенный python интерпритатор, он позволяет вести диалог напрямую с любым запущеным деревом сцен Coin3d, также как окна трехмерного отображения FreeCAD, или даже создавать новые. Pivy входит в стандвртную установку FreeCAD.
Библиотека coin разделена на несколько частей, собственно coin, для управления древами сцен и привязки к различным GUI системам, таким как windows или, в нашем случае, qt. Эти модули также доступны pivy, если они представлены в системе. Модуль coin всегда присутствует, и это то что мы будем использовать в любом случае, поэтому мы не должны хаботится о наших привзках нашего 3D отображения, к различным интерфейсам, это уже сделано в самом FreeCAD. Все что вам нужно, так это сделать ЭТО:
from pivy import coin
Получение доступа и изменение древа сцен
Мы говорили на странице Scenegraph как организована типичная Coin сцена. Все что добавляется в окно трехмерного отображения FreeCAD , coin scenegraph, организует схожим образом. у нас есть один корневой узел, и все объекты на экране его потомки.
FreeCAD обладает простым способом получит доступ к корневому узлу(вершине) древа сцена 3D вида:
sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() print sg
Это вернет корневой узел:
<pivy.coin.SoSelection; proxy of <Swig Object of type 'SoSelection *' at 0x360cb60> >
Мы сразу же можем просмотреть потомков, нашей сцены:
for node in sg.getChildren(): print node
Некоторые из этих узлов, такие как SoSeparators или SoGroups, также могут обладать потомками. Полный список доступных coin объектов можно найти в оффициальной документаци coin.
Давайте, сейчас, попробуем добавить что-нибудь в наше древо сцены. Мы добавим милейший красный куб:
col = coin.SoBaseColor() col.rgb=(1,0,0) cub = coin.SoCube() myCustomNode = coin.SoSeparator() myCustomNode.addChild(col) myCustomNode.addChild(cub) sg.addChild(myCustomNode)
и здесь наш(милый) красный куб. Теперь попробуем следующее:
col.rgb=(1,1,0)
Видите? все по прежнему доступно и изменяемо на лету. Не нужно что-нибудь пересчитывать или перересовывать, coin позаботится обо всем. Вы можете что-то в ваше древо сцен, изменить свойства, скрыть этот объект, показать временный объект, что угодно. Конечно это касается только отображения трехмерного вида. Это отображение получается при считывании FreeCAD-ом файла при открытии, и когда объект нужно перечитать. Так что, если вы изменили какой-нибудь аспект в существующем FreeCAD объекте,эти изменения будут потеряны, если объект перечитают, или же повторно откроют.
Ключ к работе с древом сцен в ваших сценариях, чтобы обладать доступом к определенным свойствам узлов вы добавляете то что вам нужно. Например, если нам нужно переместить наш куб, мы добавили бы узел SoTranslation в нашему обычному узлу, м выглядело бы это так:
col = coin.SoBaseColor() col.rgb=(1,0,0) trans = coin.SoTranslation() trans.translation.setValue([0,0,0]) cub = coin.SoCube() myCustomNode = coin.SoSeparator() myCustomNode.addChild(col) mtCustomNode.addChild(trans) myCustomNode.addChild(cub) sg.addChild(myCustomNode)
Помните, что в дереве сцен openInventor, важен порядок. Узел влияет на то что будет дальше, вы можете сказать нечто вроде: цет красны, куб, цвет желтый, сфера, и вы получите красный куб и желтую сферу. Если мы добавим перемещение сейчас в нашу существующий узел, он будет стоять после куба и не будет влиять на него. Если мы вставили его до его создания, как показано выше, мы могли бы сейчас сделать:
trans.translation.setValue([2,0,0])
И наш куб прыгает на 2 единицы вправо. Наконец, удалим что-нибудь, введя:
sg.removeChild(myCustomNode)
Использование обратных вызовов
Функция обратного вызова это система, позволяет библиотекам которые вы используете, такой как наша библиотека coin , возвращать вызов, это означает, возможность вызова определенных функций с вашего запущенного python объекта. Это очень полезно, потому что это способ которыйм coin может сообщить вам , о конкретных событиях происходящих на сцене. Coin может наблюдать за множеством различных вещей, таких как положение курсора, нажатия клавиши мыши, нажатые клавиши клавиатуры, и множество других вещей.
FreeCAD способен легко испльзовать такие функции обратного вызова:
class ButtonTest: def __init__(self): self.view = FreeCADGui.ActiveDocument.ActiveView self.callback = self.view.addEventCallbackPivy(SoMouseButtonEvent.getClassTypeId(),self.getMouseClick) def getMouseClick(self,event_cb): event = event_cb.getEvent() if event.getState() == SoMouseButtonEvent.DOWN: print "Alert!!! A mouse button has been improperly clicked!!!" self.view.removeEventCallbackSWIG(SoMouseButtonEvent.getClassTypeId(),self.callback) ButtonTest()
Функция обратного вызова, должна быть инициализирована объектом, потому что объект должен по прежнему работать, когда будут происходить обратные вызовы. Смотри также полный список возможных событий и их парамметров, или официальную документацию coin.
Документация
К сожалению сам pivy , ещё не обладает надлежащей документацией, но так как это точный перевод coin на Python, вы можете смело использовать документацию по coin как введение и используя стиль python вместо c++ стиля (например SoFile::getClassTypeId() в pivy будет SoFile.getClassId())